Remove
Showing
81 changed files
with
0 additions
and
19296 deletions
mailbox/alloca.c
deleted
100644 → 0
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 | #ifdef HAVE_CONFIG_H | ||
25 | # include <config.h> | ||
26 | #endif | ||
27 | |||
28 | #include <alloca.h> | ||
29 | |||
30 | #include <string.h> | ||
31 | #include <stdlib.h> | ||
32 | |||
33 | #ifdef emacs | ||
34 | # include "lisp.h" | ||
35 | # include "blockinput.h" | ||
36 | # ifdef EMACS_FREE | ||
37 | # undef free | ||
38 | # define free EMACS_FREE | ||
39 | # endif | ||
40 | #else | ||
41 | # define memory_full() abort () | ||
42 | #endif | ||
43 | |||
44 | /* If compiling with GCC 2, this file's not needed. */ | ||
45 | #if !defined (__GNUC__) || __GNUC__ < 2 | ||
46 | |||
47 | /* If someone has defined alloca as a macro, | ||
48 | there must be some other way alloca is supposed to work. */ | ||
49 | # ifndef alloca | ||
50 | |||
51 | # ifdef emacs | ||
52 | # ifdef static | ||
53 | /* actually, only want this if static is defined as "" | ||
54 | -- this is for usg, in which emacs must undefine static | ||
55 | in order to make unexec workable | ||
56 | */ | ||
57 | # ifndef STACK_DIRECTION | ||
58 | you | ||
59 | lose | ||
60 | -- must know STACK_DIRECTION at compile-time | ||
61 | /* Using #error here is not wise since this file should work for | ||
62 | old and obscure compilers. */ | ||
63 | # endif /* STACK_DIRECTION undefined */ | ||
64 | # endif /* static */ | ||
65 | # endif /* emacs */ | ||
66 | |||
67 | /* If your stack is a linked list of frames, you have to | ||
68 | provide an "address metric" ADDRESS_FUNCTION macro. */ | ||
69 | |||
70 | # if defined (CRAY) && defined (CRAY_STACKSEG_END) | ||
71 | long i00afunc (); | ||
72 | # define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg)) | ||
73 | # else | ||
74 | # define ADDRESS_FUNCTION(arg) &(arg) | ||
75 | # endif | ||
76 | |||
77 | /* Define STACK_DIRECTION if you know the direction of stack | ||
78 | growth for your system; otherwise it will be automatically | ||
79 | deduced at run-time. | ||
80 | |||
81 | STACK_DIRECTION > 0 => grows toward higher addresses | ||
82 | STACK_DIRECTION < 0 => grows toward lower addresses | ||
83 | STACK_DIRECTION = 0 => direction of growth unknown */ | ||
84 | |||
85 | # ifndef STACK_DIRECTION | ||
86 | # define STACK_DIRECTION 0 /* Direction unknown. */ | ||
87 | # endif | ||
88 | |||
89 | # if STACK_DIRECTION != 0 | ||
90 | |||
91 | # define STACK_DIR STACK_DIRECTION /* Known at compile-time. */ | ||
92 | |||
93 | # else /* STACK_DIRECTION == 0; need run-time code. */ | ||
94 | |||
95 | static int stack_dir; /* 1 or -1 once known. */ | ||
96 | # define STACK_DIR stack_dir | ||
97 | |||
98 | static void | ||
99 | find_stack_direction (void) | ||
100 | { | ||
101 | static char *addr = NULL; /* Address of first `dummy', once known. */ | ||
102 | auto char dummy; /* To get stack address. */ | ||
103 | |||
104 | if (addr == NULL) | ||
105 | { /* Initial entry. */ | ||
106 | addr = ADDRESS_FUNCTION (dummy); | ||
107 | |||
108 | find_stack_direction (); /* Recurse once. */ | ||
109 | } | ||
110 | else | ||
111 | { | ||
112 | /* Second entry. */ | ||
113 | if (ADDRESS_FUNCTION (dummy) > addr) | ||
114 | stack_dir = 1; /* Stack grew upward. */ | ||
115 | else | ||
116 | stack_dir = -1; /* Stack grew downward. */ | ||
117 | } | ||
118 | } | ||
119 | |||
120 | # endif /* STACK_DIRECTION == 0 */ | ||
121 | |||
122 | /* An "alloca header" is used to: | ||
123 | (a) chain together all alloca'ed blocks; | ||
124 | (b) keep track of stack depth. | ||
125 | |||
126 | It is very important that sizeof(header) agree with malloc | ||
127 | alignment chunk size. The following default should work okay. */ | ||
128 | |||
129 | # ifndef ALIGN_SIZE | ||
130 | # define ALIGN_SIZE sizeof(double) | ||
131 | # endif | ||
132 | |||
133 | typedef union hdr | ||
134 | { | ||
135 | char align[ALIGN_SIZE]; /* To force sizeof(header). */ | ||
136 | struct | ||
137 | { | ||
138 | union hdr *next; /* For chaining headers. */ | ||
139 | char *deep; /* For stack depth measure. */ | ||
140 | } h; | ||
141 | } header; | ||
142 | |||
143 | static header *last_alloca_header = NULL; /* -> last alloca header. */ | ||
144 | |||
145 | /* Return a pointer to at least SIZE bytes of storage, | ||
146 | which will be automatically reclaimed upon exit from | ||
147 | the procedure that called alloca. Originally, this space | ||
148 | was supposed to be taken from the current stack frame of the | ||
149 | caller, but that method cannot be made to work for some | ||
150 | implementations of C, for example under Gould's UTX/32. */ | ||
151 | |||
152 | void * | ||
153 | alloca (size_t size) | ||
154 | { | ||
155 | auto char probe; /* Probes stack depth: */ | ||
156 | register char *depth = ADDRESS_FUNCTION (probe); | ||
157 | |||
158 | # if STACK_DIRECTION == 0 | ||
159 | if (STACK_DIR == 0) /* Unknown growth direction. */ | ||
160 | find_stack_direction (); | ||
161 | # endif | ||
162 | |||
163 | /* Reclaim garbage, defined as all alloca'd storage that | ||
164 | was allocated from deeper in the stack than currently. */ | ||
165 | |||
166 | { | ||
167 | register header *hp; /* Traverses linked list. */ | ||
168 | |||
169 | # ifdef emacs | ||
170 | BLOCK_INPUT; | ||
171 | # endif | ||
172 | |||
173 | for (hp = last_alloca_header; hp != NULL;) | ||
174 | if ((STACK_DIR > 0 && hp->h.deep > depth) | ||
175 | || (STACK_DIR < 0 && hp->h.deep < depth)) | ||
176 | { | ||
177 | register header *np = hp->h.next; | ||
178 | |||
179 | free (hp); /* Collect garbage. */ | ||
180 | |||
181 | hp = np; /* -> next header. */ | ||
182 | } | ||
183 | else | ||
184 | break; /* Rest are not deeper. */ | ||
185 | |||
186 | last_alloca_header = hp; /* -> last valid storage. */ | ||
187 | |||
188 | # ifdef emacs | ||
189 | UNBLOCK_INPUT; | ||
190 | # endif | ||
191 | } | ||
192 | |||
193 | if (size == 0) | ||
194 | return NULL; /* No allocation required. */ | ||
195 | |||
196 | /* Allocate combined header + user data storage. */ | ||
197 | |||
198 | { | ||
199 | /* Address of header. */ | ||
200 | register header *new; | ||
201 | |||
202 | size_t combined_size = sizeof (header) + size; | ||
203 | if (combined_size < sizeof (header)) | ||
204 | memory_full (); | ||
205 | |||
206 | new = malloc (combined_size); | ||
207 | |||
208 | if (! new) | ||
209 | memory_full (); | ||
210 | |||
211 | new->h.next = last_alloca_header; | ||
212 | new->h.deep = depth; | ||
213 | |||
214 | last_alloca_header = new; | ||
215 | |||
216 | /* User storage begins just after header. */ | ||
217 | |||
218 | return (void *) (new + 1); | ||
219 | } | ||
220 | } | ||
221 | |||
222 | # if defined (CRAY) && defined (CRAY_STACKSEG_END) | ||
223 | |||
224 | # ifdef DEBUG_I00AFUNC | ||
225 | # include <stdio.h> | ||
226 | # endif | ||
227 | |||
228 | # ifndef CRAY_STACK | ||
229 | # define CRAY_STACK | ||
230 | # ifndef CRAY2 | ||
231 | /* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ | ||
232 | struct stack_control_header | ||
233 | { | ||
234 | long shgrow:32; /* Number of times stack has grown. */ | ||
235 | long shaseg:32; /* Size of increments to stack. */ | ||
236 | long shhwm:32; /* High water mark of stack. */ | ||
237 | long shsize:32; /* Current size of stack (all segments). */ | ||
238 | }; | ||
239 | |||
240 | /* The stack segment linkage control information occurs at | ||
241 | the high-address end of a stack segment. (The stack | ||
242 | grows from low addresses to high addresses.) The initial | ||
243 | part of the stack segment linkage control information is | ||
244 | 0200 (octal) words. This provides for register storage | ||
245 | for the routine which overflows the stack. */ | ||
246 | |||
247 | struct stack_segment_linkage | ||
248 | { | ||
249 | long ss[0200]; /* 0200 overflow words. */ | ||
250 | long sssize:32; /* Number of words in this segment. */ | ||
251 | long ssbase:32; /* Offset to stack base. */ | ||
252 | long:32; | ||
253 | long sspseg:32; /* Offset to linkage control of previous | ||
254 | segment of stack. */ | ||
255 | long:32; | ||
256 | long sstcpt:32; /* Pointer to task common address block. */ | ||
257 | long sscsnm; /* Private control structure number for | ||
258 | microtasking. */ | ||
259 | long ssusr1; /* Reserved for user. */ | ||
260 | long ssusr2; /* Reserved for user. */ | ||
261 | long sstpid; /* Process ID for pid based multi-tasking. */ | ||
262 | long ssgvup; /* Pointer to multitasking thread giveup. */ | ||
263 | long sscray[7]; /* Reserved for Cray Research. */ | ||
264 | long ssa0; | ||
265 | long ssa1; | ||
266 | long ssa2; | ||
267 | long ssa3; | ||
268 | long ssa4; | ||
269 | long ssa5; | ||
270 | long ssa6; | ||
271 | long ssa7; | ||
272 | long sss0; | ||
273 | long sss1; | ||
274 | long sss2; | ||
275 | long sss3; | ||
276 | long sss4; | ||
277 | long sss5; | ||
278 | long sss6; | ||
279 | long sss7; | ||
280 | }; | ||
281 | |||
282 | # else /* CRAY2 */ | ||
283 | /* The following structure defines the vector of words | ||
284 | returned by the STKSTAT library routine. */ | ||
285 | struct stk_stat | ||
286 | { | ||
287 | long now; /* Current total stack size. */ | ||
288 | long maxc; /* Amount of contiguous space which would | ||
289 | be required to satisfy the maximum | ||
290 | stack demand to date. */ | ||
291 | long high_water; /* Stack high-water mark. */ | ||
292 | long overflows; /* Number of stack overflow ($STKOFEN) calls. */ | ||
293 | long hits; /* Number of internal buffer hits. */ | ||
294 | long extends; /* Number of block extensions. */ | ||
295 | long stko_mallocs; /* Block allocations by $STKOFEN. */ | ||
296 | long underflows; /* Number of stack underflow calls ($STKRETN). */ | ||
297 | long stko_free; /* Number of deallocations by $STKRETN. */ | ||
298 | long stkm_free; /* Number of deallocations by $STKMRET. */ | ||
299 | long segments; /* Current number of stack segments. */ | ||
300 | long maxs; /* Maximum number of stack segments so far. */ | ||
301 | long pad_size; /* Stack pad size. */ | ||
302 | long current_address; /* Current stack segment address. */ | ||
303 | long current_size; /* Current stack segment size. This | ||
304 | number is actually corrupted by STKSTAT to | ||
305 | include the fifteen word trailer area. */ | ||
306 | long initial_address; /* Address of initial segment. */ | ||
307 | long initial_size; /* Size of initial segment. */ | ||
308 | }; | ||
309 | |||
310 | /* The following structure describes the data structure which trails | ||
311 | any stack segment. I think that the description in 'asdef' is | ||
312 | out of date. I only describe the parts that I am sure about. */ | ||
313 | |||
314 | struct stk_trailer | ||
315 | { | ||
316 | long this_address; /* Address of this block. */ | ||
317 | long this_size; /* Size of this block (does not include | ||
318 | this trailer). */ | ||
319 | long unknown2; | ||
320 | long unknown3; | ||
321 | long link; /* Address of trailer block of previous | ||
322 | segment. */ | ||
323 | long unknown5; | ||
324 | long unknown6; | ||
325 | long unknown7; | ||
326 | long unknown8; | ||
327 | long unknown9; | ||
328 | long unknown10; | ||
329 | long unknown11; | ||
330 | long unknown12; | ||
331 | long unknown13; | ||
332 | long unknown14; | ||
333 | }; | ||
334 | |||
335 | # endif /* CRAY2 */ | ||
336 | # endif /* not CRAY_STACK */ | ||
337 | |||
338 | # ifdef CRAY2 | ||
339 | /* Determine a "stack measure" for an arbitrary ADDRESS. | ||
340 | I doubt that "lint" will like this much. */ | ||
341 | |||
342 | static long | ||
343 | i00afunc (long *address) | ||
344 | { | ||
345 | struct stk_stat status; | ||
346 | struct stk_trailer *trailer; | ||
347 | long *block, size; | ||
348 | long result = 0; | ||
349 | |||
350 | /* We want to iterate through all of the segments. The first | ||
351 | step is to get the stack status structure. We could do this | ||
352 | more quickly and more directly, perhaps, by referencing the | ||
353 | $LM00 common block, but I know that this works. */ | ||
354 | |||
355 | STKSTAT (&status); | ||
356 | |||
357 | /* Set up the iteration. */ | ||
358 | |||
359 | trailer = (struct stk_trailer *) (status.current_address | ||
360 | + status.current_size | ||
361 | - 15); | ||
362 | |||
363 | /* There must be at least one stack segment. Therefore it is | ||
364 | a fatal error if "trailer" is null. */ | ||
365 | |||
366 | if (trailer == 0) | ||
367 | abort (); | ||
368 | |||
369 | /* Discard segments that do not contain our argument address. */ | ||
370 | |||
371 | while (trailer != 0) | ||
372 | { | ||
373 | block = (long *) trailer->this_address; | ||
374 | size = trailer->this_size; | ||
375 | if (block == 0 || size == 0) | ||
376 | abort (); | ||
377 | trailer = (struct stk_trailer *) trailer->link; | ||
378 | if ((block <= address) && (address < (block + size))) | ||
379 | break; | ||
380 | } | ||
381 | |||
382 | /* Set the result to the offset in this segment and add the sizes | ||
383 | of all predecessor segments. */ | ||
384 | |||
385 | result = address - block; | ||
386 | |||
387 | if (trailer == 0) | ||
388 | { | ||
389 | return result; | ||
390 | } | ||
391 | |||
392 | do | ||
393 | { | ||
394 | if (trailer->this_size <= 0) | ||
395 | abort (); | ||
396 | result += trailer->this_size; | ||
397 | trailer = (struct stk_trailer *) trailer->link; | ||
398 | } | ||
399 | while (trailer != 0); | ||
400 | |||
401 | /* We are done. Note that if you present a bogus address (one | ||
402 | not in any segment), you will get a different number back, formed | ||
403 | from subtracting the address of the first block. This is probably | ||
404 | not what you want. */ | ||
405 | |||
406 | return (result); | ||
407 | } | ||
408 | |||
409 | # else /* not CRAY2 */ | ||
410 | /* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP. | ||
411 | Determine the number of the cell within the stack, | ||
412 | given the address of the cell. The purpose of this | ||
413 | routine is to linearize, in some sense, stack addresses | ||
414 | for alloca. */ | ||
415 | |||
416 | static long | ||
417 | i00afunc (long address) | ||
418 | { | ||
419 | long stkl = 0; | ||
420 | |||
421 | long size, pseg, this_segment, stack; | ||
422 | long result = 0; | ||
423 | |||
424 | struct stack_segment_linkage *ssptr; | ||
425 | |||
426 | /* Register B67 contains the address of the end of the | ||
427 | current stack segment. If you (as a subprogram) store | ||
428 | your registers on the stack and find that you are past | ||
429 | the contents of B67, you have overflowed the segment. | ||
430 | |||
431 | B67 also points to the stack segment linkage control | ||
432 | area, which is what we are really interested in. */ | ||
433 | |||
434 | stkl = CRAY_STACKSEG_END (); | ||
435 | ssptr = (struct stack_segment_linkage *) stkl; | ||
436 | |||
437 | /* If one subtracts 'size' from the end of the segment, | ||
438 | one has the address of the first word of the segment. | ||
439 | |||
440 | If this is not the first segment, 'pseg' will be | ||
441 | nonzero. */ | ||
442 | |||
443 | pseg = ssptr->sspseg; | ||
444 | size = ssptr->sssize; | ||
445 | |||
446 | this_segment = stkl - size; | ||
447 | |||
448 | /* It is possible that calling this routine itself caused | ||
449 | a stack overflow. Discard stack segments which do not | ||
450 | contain the target address. */ | ||
451 | |||
452 | while (!(this_segment <= address && address <= stkl)) | ||
453 | { | ||
454 | # ifdef DEBUG_I00AFUNC | ||
455 | fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl); | ||
456 | # endif | ||
457 | if (pseg == 0) | ||
458 | break; | ||
459 | stkl = stkl - pseg; | ||
460 | ssptr = (struct stack_segment_linkage *) stkl; | ||
461 | size = ssptr->sssize; | ||
462 | pseg = ssptr->sspseg; | ||
463 | this_segment = stkl - size; | ||
464 | } | ||
465 | |||
466 | result = address - this_segment; | ||
467 | |||
468 | /* If you subtract pseg from the current end of the stack, | ||
469 | you get the address of the previous stack segment's end. | ||
470 | This seems a little convoluted to me, but I'll bet you save | ||
471 | a cycle somewhere. */ | ||
472 | |||
473 | while (pseg != 0) | ||
474 | { | ||
475 | # ifdef DEBUG_I00AFUNC | ||
476 | fprintf (stderr, "%011o %011o\n", pseg, size); | ||
477 | # endif | ||
478 | stkl = stkl - pseg; | ||
479 | ssptr = (struct stack_segment_linkage *) stkl; | ||
480 | size = ssptr->sssize; | ||
481 | pseg = ssptr->sspseg; | ||
482 | result += size; | ||
483 | } | ||
484 | return (result); | ||
485 | } | ||
486 | |||
487 | # endif /* not CRAY2 */ | ||
488 | # endif /* CRAY */ | ||
489 | |||
490 | # endif /* no alloca */ | ||
491 | #endif /* not GCC version 2 */ |
mailbox/alloca_.h
deleted
100644 → 0
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 | ||
48 | extern "C" | ||
49 | # endif | ||
50 | void *alloca (size_t); | ||
51 | # endif | ||
52 | #endif | ||
53 | |||
54 | #endif /* _GNULIB_ALLOCA_H */ |
mailbox/argp-ba.c
deleted
100644 → 0
1 | /* Default definition for ARGP_PROGRAM_BUG_ADDRESS. | ||
2 | Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. | ||
3 | This file is part of the GNU C Library. | ||
4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. | ||
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 | /* If set by the user program, it should point to string that is the | ||
21 | bug-reporting address for the program. It will be printed by argp_help if | ||
22 | the ARGP_HELP_BUG_ADDR flag is set (as it is by various standard help | ||
23 | messages), embedded in a sentence that says something like `Report bugs to | ||
24 | ADDR.'. */ | ||
25 | const char *argp_program_bug_address; |
mailbox/argp-eexst.c
deleted
100644 → 0
1 | /* Default definition for ARGP_ERR_EXIT_STATUS | ||
2 | Copyright (C) 1997 Free Software Foundation, Inc. | ||
3 | This file is part of the GNU C Library. | ||
4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. | ||
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 HAVE_CONFIG_H | ||
21 | # include <config.h> | ||
22 | #endif | ||
23 | |||
24 | #include <sysexits.h> | ||
25 | |||
26 | #include "argp.h" | ||
27 | |||
28 | /* The exit status that argp will use when exiting due to a parsing error. | ||
29 | If not defined or set by the user program, this defaults to EX_USAGE from | ||
30 | <sysexits.h>. */ | ||
31 | error_t argp_err_exit_status = EX_USAGE; |
mailbox/argp-fmtstream.c
deleted
100644 → 0
1 | /* Word-wrapping and line-truncating streams | ||
2 | Copyright (C) 1997-1999,2001,2002,2003,2005 Free Software Foundation, Inc. | ||
3 | This file is part of the GNU C Library. | ||
4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. | ||
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 | /* This package emulates glibc `line_wrap_stream' semantics for systems that | ||
21 | don't have that. */ | ||
22 | |||
23 | #ifdef HAVE_CONFIG_H | ||
24 | # include <config.h> | ||
25 | #endif | ||
26 | |||
27 | #include <stdlib.h> | ||
28 | #include <string.h> | ||
29 | #include <errno.h> | ||
30 | #include <stdarg.h> | ||
31 | #include <ctype.h> | ||
32 | |||
33 | #include "argp-fmtstream.h" | ||
34 | #include "argp-namefrob.h" | ||
35 | |||
36 | #ifndef ARGP_FMTSTREAM_USE_LINEWRAP | ||
37 | |||
38 | #ifndef isblank | ||
39 | #define isblank(ch) ((ch)==' ' || (ch)=='\t') | ||
40 | #endif | ||
41 | |||
42 | #if defined _LIBC && defined USE_IN_LIBIO | ||
43 | # include <wchar.h> | ||
44 | # include <libio/libioP.h> | ||
45 | # define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a) | ||
46 | #endif | ||
47 | |||
48 | #define INIT_BUF_SIZE 200 | ||
49 | #define PRINTF_SIZE_GUESS 150 | ||
50 | |||
51 | /* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines | ||
52 | written on it with LMARGIN spaces and limits them to RMARGIN columns | ||
53 | total. If WMARGIN >= 0, words that extend past RMARGIN are wrapped by | ||
54 | replacing the whitespace before them with a newline and WMARGIN spaces. | ||
55 | Otherwise, chars beyond RMARGIN are simply dropped until a newline. | ||
56 | Returns NULL if there was an error. */ | ||
57 | argp_fmtstream_t | ||
58 | __argp_make_fmtstream (FILE *stream, | ||
59 | size_t lmargin, size_t rmargin, ssize_t wmargin) | ||
60 | { | ||
61 | argp_fmtstream_t fs; | ||
62 | |||
63 | fs = (struct argp_fmtstream *) malloc (sizeof (struct argp_fmtstream)); | ||
64 | if (fs != NULL) | ||
65 | { | ||
66 | fs->stream = stream; | ||
67 | |||
68 | fs->lmargin = lmargin; | ||
69 | fs->rmargin = rmargin; | ||
70 | fs->wmargin = wmargin; | ||
71 | fs->point_col = 0; | ||
72 | fs->point_offs = 0; | ||
73 | |||
74 | fs->buf = (char *) malloc (INIT_BUF_SIZE); | ||
75 | if (! fs->buf) | ||
76 | { | ||
77 | free (fs); | ||
78 | fs = 0; | ||
79 | } | ||
80 | else | ||
81 | { | ||
82 | fs->p = fs->buf; | ||
83 | fs->end = fs->buf + INIT_BUF_SIZE; | ||
84 | } | ||
85 | } | ||
86 | |||
87 | return fs; | ||
88 | } | ||
89 | #if 0 | ||
90 | /* Not exported. */ | ||
91 | #ifdef weak_alias | ||
92 | weak_alias (__argp_make_fmtstream, argp_make_fmtstream) | ||
93 | #endif | ||
94 | #endif | ||
95 | |||
96 | /* Flush FS to its stream, and free it (but don't close the stream). */ | ||
97 | void | ||
98 | __argp_fmtstream_free (argp_fmtstream_t fs) | ||
99 | { | ||
100 | __argp_fmtstream_update (fs); | ||
101 | if (fs->p > fs->buf) | ||
102 | { | ||
103 | #ifdef USE_IN_LIBIO | ||
104 | __fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf); | ||
105 | #else | ||
106 | fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream); | ||
107 | #endif | ||
108 | } | ||
109 | free (fs->buf); | ||
110 | free (fs); | ||
111 | } | ||
112 | #if 0 | ||
113 | /* Not exported. */ | ||
114 | #ifdef weak_alias | ||
115 | weak_alias (__argp_fmtstream_free, argp_fmtstream_free) | ||
116 | #endif | ||
117 | #endif | ||
118 | |||
119 | /* Process FS's buffer so that line wrapping is done from POINT_OFFS to the | ||
120 | end of its buffer. This code is mostly from glibc stdio/linewrap.c. */ | ||
121 | void | ||
122 | __argp_fmtstream_update (argp_fmtstream_t fs) | ||
123 | { | ||
124 | char *buf, *nl; | ||
125 | size_t len; | ||
126 | |||
127 | /* Scan the buffer for newlines. */ | ||
128 | buf = fs->buf + fs->point_offs; | ||
129 | while (buf < fs->p) | ||
130 | { | ||
131 | size_t r; | ||
132 | |||
133 | if (fs->point_col == 0 && fs->lmargin != 0) | ||
134 | { | ||
135 | /* We are starting a new line. Print spaces to the left margin. */ | ||
136 | const size_t pad = fs->lmargin; | ||
137 | if (fs->p + pad < fs->end) | ||
138 | { | ||
139 | /* We can fit in them in the buffer by moving the | ||
140 | buffer text up and filling in the beginning. */ | ||
141 | memmove (buf + pad, buf, fs->p - buf); | ||
142 | fs->p += pad; /* Compensate for bigger buffer. */ | ||
143 | memset (buf, ' ', pad); /* Fill in the spaces. */ | ||
144 | buf += pad; /* Don't bother searching them. */ | ||
145 | } | ||
146 | else | ||
147 | { | ||
148 | /* No buffer space for spaces. Must flush. */ | ||
149 | size_t i; | ||
150 | for (i = 0; i < pad; i++) | ||
151 | { | ||
152 | #ifdef USE_IN_LIBIO | ||
153 | if (_IO_fwide (fs->stream, 0) > 0) | ||
154 | putwc_unlocked (L' ', fs->stream); | ||
155 | else | ||
156 | #endif | ||
157 | putc_unlocked (' ', fs->stream); | ||
158 | } | ||
159 | } | ||
160 | fs->point_col = pad; | ||
161 | } | ||
162 | |||
163 | len = fs->p - buf; | ||
164 | nl = memchr (buf, '\n', len); | ||
165 | |||
166 | if (fs->point_col < 0) | ||
167 | fs->point_col = 0; | ||
168 | |||
169 | if (!nl) | ||
170 | { | ||
171 | /* The buffer ends in a partial line. */ | ||
172 | |||
173 | if (fs->point_col + len < fs->rmargin) | ||
174 | { | ||
175 | /* The remaining buffer text is a partial line and fits | ||
176 | within the maximum line width. Advance point for the | ||
177 | characters to be written and stop scanning. */ | ||
178 | fs->point_col += len; | ||
179 | break; | ||
180 | } | ||
181 | else | ||
182 | /* Set the end-of-line pointer for the code below to | ||
183 | the end of the buffer. */ | ||
184 | nl = fs->p; | ||
185 | } | ||
186 | else if (fs->point_col + (nl - buf) < (ssize_t) fs->rmargin) | ||
187 | { | ||
188 | /* The buffer contains a full line that fits within the maximum | ||
189 | line width. Reset point and scan the next line. */ | ||
190 | fs->point_col = 0; | ||
191 | buf = nl + 1; | ||
192 | continue; | ||
193 | } | ||
194 | |||
195 | /* This line is too long. */ | ||
196 | r = fs->rmargin - 1; | ||
197 | |||
198 | if (fs->wmargin < 0) | ||
199 | { | ||
200 | /* Truncate the line by overwriting the excess with the | ||
201 | newline and anything after it in the buffer. */ | ||
202 | if (nl < fs->p) | ||
203 | { | ||
204 | memmove (buf + (r - fs->point_col), nl, fs->p - nl); | ||
205 | fs->p -= buf + (r - fs->point_col) - nl; | ||
206 | /* Reset point for the next line and start scanning it. */ | ||
207 | fs->point_col = 0; | ||
208 | buf += r + 1; /* Skip full line plus \n. */ | ||
209 | } | ||
210 | else | ||
211 | { | ||
212 | /* The buffer ends with a partial line that is beyond the | ||
213 | maximum line width. Advance point for the characters | ||
214 | written, and discard those past the max from the buffer. */ | ||
215 | fs->point_col += len; | ||
216 | fs->p -= fs->point_col - r; | ||
217 | break; | ||
218 | } | ||
219 | } | ||
220 | else | ||
221 | { | ||
222 | /* Do word wrap. Go to the column just past the maximum line | ||
223 | width and scan back for the beginning of the word there. | ||
224 | Then insert a line break. */ | ||
225 | |||
226 | char *p, *nextline; | ||
227 | int i; | ||
228 | |||
229 | p = buf + (r + 1 - fs->point_col); | ||
230 | while (p >= buf && !isblank (*p)) | ||
231 | --p; | ||
232 | nextline = p + 1; /* This will begin the next line. */ | ||
233 | |||
234 | if (nextline > buf) | ||
235 | { | ||
236 | /* Swallow separating blanks. */ | ||
237 | if (p >= buf) | ||
238 | do | ||
239 | --p; | ||
240 | while (p >= buf && isblank (*p)); | ||
241 | nl = p + 1; /* The newline will replace the first blank. */ | ||
242 | } | ||
243 | else | ||
244 | { | ||
245 | /* A single word that is greater than the maximum line width. | ||
246 | Oh well. Put it on an overlong line by itself. */ | ||
247 | p = buf + (r + 1 - fs->point_col); | ||
248 | /* Find the end of the long word. */ | ||
249 | if (p < nl) | ||
250 | do | ||
251 | ++p; | ||
252 | while (p < nl && !isblank (*p)); | ||
253 | if (p == nl) | ||
254 | { | ||
255 | /* It already ends a line. No fussing required. */ | ||
256 | fs->point_col = 0; | ||
257 | buf = nl + 1; | ||
258 | continue; | ||
259 | } | ||
260 | /* We will move the newline to replace the first blank. */ | ||
261 | nl = p; | ||
262 | /* Swallow separating blanks. */ | ||
263 | do | ||
264 | ++p; | ||
265 | while (isblank (*p)); | ||
266 | /* The next line will start here. */ | ||
267 | nextline = p; | ||
268 | } | ||
269 | |||
270 | /* Note: There are a bunch of tests below for | ||
271 | NEXTLINE == BUF + LEN + 1; this case is where NL happens to fall | ||
272 | at the end of the buffer, and NEXTLINE is in fact empty (and so | ||
273 | we need not be careful to maintain its contents). */ | ||
274 | |||
275 | if ((nextline == buf + len + 1 | ||
276 | ? fs->end - nl < fs->wmargin + 1 | ||
277 | : nextline - (nl + 1) < fs->wmargin) | ||
278 | && fs->p > nextline) | ||
279 | { | ||
280 | /* The margin needs more blanks than we removed. */ | ||
281 | if (fs->end - fs->p > fs->wmargin + 1) | ||
282 | /* Make some space for them. */ | ||
283 | { | ||
284 | size_t mv = fs->p - nextline; | ||
285 | memmove (nl + 1 + fs->wmargin, nextline, mv); | ||
286 | nextline = nl + 1 + fs->wmargin; | ||
287 | len = nextline + mv - buf; | ||
288 | *nl++ = '\n'; | ||
289 | } | ||
290 | else | ||
291 | /* Output the first line so we can use the space. */ | ||
292 | { | ||
293 | #ifdef _LIBC | ||
294 | __fxprintf (fs->stream, "%.*s\n", | ||
295 | (int) (nl - fs->buf), fs->buf); | ||
296 | #else | ||
297 | if (nl > fs->buf) | ||
298 | fwrite_unlocked (fs->buf, 1, nl - fs->buf, fs->stream); | ||
299 | putc_unlocked ('\n', fs->stream); | ||
300 | #endif | ||
301 | |||
302 | len += buf - fs->buf; | ||
303 | nl = buf = fs->buf; | ||
304 | } | ||
305 | } | ||
306 | else | ||
307 | /* We can fit the newline and blanks in before | ||
308 | the next word. */ | ||
309 | *nl++ = '\n'; | ||
310 | |||
311 | if (nextline - nl >= fs->wmargin | ||
312 | || (nextline == buf + len + 1 && fs->end - nextline >= fs->wmargin)) | ||
313 | /* Add blanks up to the wrap margin column. */ | ||
314 | for (i = 0; i < fs->wmargin; ++i) | ||
315 | *nl++ = ' '; | ||
316 | else | ||
317 | for (i = 0; i < fs->wmargin; ++i) | ||
318 | #ifdef USE_IN_LIBIO | ||
319 | if (_IO_fwide (fs->stream, 0) > 0) | ||
320 | putwc_unlocked (L' ', fs->stream); | ||
321 | else | ||
322 | #endif | ||
323 | putc_unlocked (' ', fs->stream); | ||
324 | |||
325 | /* Copy the tail of the original buffer into the current buffer | ||
326 | position. */ | ||
327 | if (nl < nextline) | ||
328 | memmove (nl, nextline, buf + len - nextline); | ||
329 | len -= nextline - buf; | ||
330 | |||
331 | /* Continue the scan on the remaining lines in the buffer. */ | ||
332 | buf = nl; | ||
333 | |||
334 | /* Restore bufp to include all the remaining text. */ | ||
335 | fs->p = nl + len; | ||
336 | |||
337 | /* Reset the counter of what has been output this line. If wmargin | ||
338 | is 0, we want to avoid the lmargin getting added, so we set | ||
339 | point_col to a magic value of -1 in that case. */ | ||
340 | fs->point_col = fs->wmargin ? fs->wmargin : -1; | ||
341 | } | ||
342 | } | ||
343 | |||
344 | /* Remember that we've scanned as far as the end of the buffer. */ | ||
345 | fs->point_offs = fs->p - fs->buf; | ||
346 | } | ||
347 | |||
348 | /* Ensure that FS has space for AMOUNT more bytes in its buffer, either by | ||
349 | growing the buffer, or by flushing it. True is returned iff we succeed. */ | ||
350 | int | ||
351 | __argp_fmtstream_ensure (struct argp_fmtstream *fs, size_t amount) | ||
352 | { | ||
353 | if ((size_t) (fs->end - fs->p) < amount) | ||
354 | { | ||
355 | ssize_t wrote; | ||
356 | |||
357 | /* Flush FS's buffer. */ | ||
358 | __argp_fmtstream_update (fs); | ||
359 | |||
360 | #ifdef _LIBC | ||
361 | __fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf); | ||
362 | wrote = fs->p - fs->buf; | ||
363 | #else | ||
364 | wrote = fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream); | ||
365 | #endif | ||
366 | if (wrote == fs->p - fs->buf) | ||
367 | { | ||
368 | fs->p = fs->buf; | ||
369 | fs->point_offs = 0; | ||
370 | } | ||
371 | else | ||
372 | { | ||
373 | fs->p -= wrote; | ||
374 | fs->point_offs -= wrote; | ||
375 | memmove (fs->buf, fs->buf + wrote, fs->p - fs->buf); | ||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | if ((size_t) (fs->end - fs->buf) < amount) | ||
380 | /* Gotta grow the buffer. */ | ||
381 | { | ||
382 | size_t old_size = fs->end - fs->buf; | ||
383 | size_t new_size = old_size + amount; | ||
384 | char *new_buf; | ||
385 | |||
386 | if (new_size < old_size || ! (new_buf = realloc (fs->buf, new_size))) | ||
387 | { | ||
388 | __set_errno (ENOMEM); | ||
389 | return 0; | ||
390 | } | ||
391 | |||
392 | fs->buf = new_buf; | ||
393 | fs->end = new_buf + new_size; | ||
394 | fs->p = fs->buf; | ||
395 | } | ||
396 | } | ||
397 | |||
398 | return 1; | ||
399 | } | ||
400 | |||
401 | ssize_t | ||
402 | __argp_fmtstream_printf (struct argp_fmtstream *fs, const char *fmt, ...) | ||
403 | { | ||
404 | int out; | ||
405 | size_t avail; | ||
406 | size_t size_guess = PRINTF_SIZE_GUESS; /* How much space to reserve. */ | ||
407 | |||
408 | do | ||
409 | { | ||
410 | va_list args; | ||
411 | |||
412 | if (! __argp_fmtstream_ensure (fs, size_guess)) | ||
413 | return -1; | ||
414 | |||
415 | va_start (args, fmt); | ||
416 | avail = fs->end - fs->p; | ||
417 | out = __vsnprintf (fs->p, avail, fmt, args); | ||
418 | va_end (args); | ||
419 | if ((size_t) out >= avail) | ||
420 | size_guess = out + 1; | ||
421 | } | ||
422 | while ((size_t) out >= avail); | ||
423 | |||
424 | fs->p += out; | ||
425 | |||
426 | return out; | ||
427 | } | ||
428 | #if 0 | ||
429 | /* Not exported. */ | ||
430 | #ifdef weak_alias | ||
431 | weak_alias (__argp_fmtstream_printf, argp_fmtstream_printf) | ||
432 | #endif | ||
433 | #endif | ||
434 | |||
435 | #endif /* !ARGP_FMTSTREAM_USE_LINEWRAP */ |
mailbox/argp-fmtstream.h
deleted
100644 → 0
1 | /* Word-wrapping and line-truncating streams. | ||
2 | Copyright (C) 1997, 2006 Free Software Foundation, Inc. | ||
3 | This file is part of the GNU C Library. | ||
4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. | ||
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 | /* This package emulates glibc `line_wrap_stream' semantics for systems that | ||
21 | don't have that. If the system does have it, it is just a wrapper for | ||
22 | that. This header file is only used internally while compiling argp, and | ||
23 | shouldn't be installed. */ | ||
24 | |||
25 | #ifndef _ARGP_FMTSTREAM_H | ||
26 | #define _ARGP_FMTSTREAM_H | ||
27 | |||
28 | #include <stdio.h> | ||
29 | #include <string.h> | ||
30 | #include <unistd.h> | ||
31 | |||
32 | #ifndef __attribute__ | ||
33 | /* This feature is available in gcc versions 2.5 and later. */ | ||
34 | # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__ | ||
35 | # define __attribute__(Spec) /* empty */ | ||
36 | # endif | ||
37 | /* The __-protected variants of `format' and `printf' attributes | ||
38 | are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ | ||
39 | # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) || __STRICT_ANSI__ | ||
40 | # define __format__ format | ||
41 | # define __printf__ printf | ||
42 | # endif | ||
43 | #endif | ||
44 | |||
45 | #if (_LIBC - 0 && !defined (USE_IN_LIBIO)) \ | ||
46 | || (defined (__GNU_LIBRARY__) && defined (HAVE_LINEWRAP_H)) | ||
47 | /* line_wrap_stream is available, so use that. */ | ||
48 | #define ARGP_FMTSTREAM_USE_LINEWRAP | ||
49 | #endif | ||
50 | |||
51 | #ifdef ARGP_FMTSTREAM_USE_LINEWRAP | ||
52 | /* Just be a simple wrapper for line_wrap_stream; the semantics are | ||
53 | *slightly* different, as line_wrap_stream doesn't actually make a new | ||
54 | object, it just modifies the given stream (reversibly) to do | ||
55 | line-wrapping. Since we control who uses this code, it doesn't matter. */ | ||
56 | |||
57 | #include <linewrap.h> | ||
58 | |||
59 | typedef FILE *argp_fmtstream_t; | ||
60 | |||
61 | #define argp_make_fmtstream line_wrap_stream | ||
62 | #define __argp_make_fmtstream line_wrap_stream | ||
63 | #define argp_fmtstream_free line_unwrap_stream | ||
64 | #define __argp_fmtstream_free line_unwrap_stream | ||
65 | |||
66 | #define __argp_fmtstream_putc(fs,ch) putc(ch,fs) | ||
67 | #define argp_fmtstream_putc(fs,ch) putc(ch,fs) | ||
68 | #define __argp_fmtstream_puts(fs,str) fputs(str,fs) | ||
69 | #define argp_fmtstream_puts(fs,str) fputs(str,fs) | ||
70 | #define __argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs) | ||
71 | #define argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs) | ||
72 | #define __argp_fmtstream_printf fprintf | ||
73 | #define argp_fmtstream_printf fprintf | ||
74 | |||
75 | #define __argp_fmtstream_lmargin line_wrap_lmargin | ||
76 | #define argp_fmtstream_lmargin line_wrap_lmargin | ||
77 | #define __argp_fmtstream_set_lmargin line_wrap_set_lmargin | ||
78 | #define argp_fmtstream_set_lmargin line_wrap_set_lmargin | ||
79 | #define __argp_fmtstream_rmargin line_wrap_rmargin | ||
80 | #define argp_fmtstream_rmargin line_wrap_rmargin | ||
81 | #define __argp_fmtstream_set_rmargin line_wrap_set_rmargin | ||
82 | #define argp_fmtstream_set_rmargin line_wrap_set_rmargin | ||
83 | #define __argp_fmtstream_wmargin line_wrap_wmargin | ||
84 | #define argp_fmtstream_wmargin line_wrap_wmargin | ||
85 | #define __argp_fmtstream_set_wmargin line_wrap_set_wmargin | ||
86 | #define argp_fmtstream_set_wmargin line_wrap_set_wmargin | ||
87 | #define __argp_fmtstream_point line_wrap_point | ||
88 | #define argp_fmtstream_point line_wrap_point | ||
89 | |||
90 | #else /* !ARGP_FMTSTREAM_USE_LINEWRAP */ | ||
91 | /* Guess we have to define our own version. */ | ||
92 | |||
93 | struct argp_fmtstream | ||
94 | { | ||
95 | FILE *stream; /* The stream we're outputting to. */ | ||
96 | |||
97 | size_t lmargin, rmargin; /* Left and right margins. */ | ||
98 | ssize_t wmargin; /* Margin to wrap to, or -1 to truncate. */ | ||
99 | |||
100 | /* Point in buffer to which we've processed for wrapping, but not output. */ | ||
101 | size_t point_offs; | ||
102 | /* Output column at POINT_OFFS, or -1 meaning 0 but don't add lmargin. */ | ||
103 | ssize_t point_col; | ||
104 | |||
105 | char *buf; /* Output buffer. */ | ||
106 | char *p; /* Current end of text in BUF. */ | ||
107 | char *end; /* Absolute end of BUF. */ | ||
108 | }; | ||
109 | |||
110 | typedef struct argp_fmtstream *argp_fmtstream_t; | ||
111 | |||
112 | /* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines | ||
113 | written on it with LMARGIN spaces and limits them to RMARGIN columns | ||
114 | total. If WMARGIN >= 0, words that extend past RMARGIN are wrapped by | ||
115 | replacing the whitespace before them with a newline and WMARGIN spaces. | ||
116 | Otherwise, chars beyond RMARGIN are simply dropped until a newline. | ||
117 | Returns NULL if there was an error. */ | ||
118 | extern argp_fmtstream_t __argp_make_fmtstream (FILE *__stream, | ||
119 | size_t __lmargin, | ||
120 | size_t __rmargin, | ||
121 | ssize_t __wmargin); | ||
122 | extern argp_fmtstream_t argp_make_fmtstream (FILE *__stream, | ||
123 | size_t __lmargin, | ||
124 | size_t __rmargin, | ||
125 | ssize_t __wmargin); | ||
126 | |||
127 | /* Flush __FS to its stream, and free it (but don't close the stream). */ | ||
128 | extern void __argp_fmtstream_free (argp_fmtstream_t __fs); | ||
129 | extern void argp_fmtstream_free (argp_fmtstream_t __fs); | ||
130 | |||
131 | extern ssize_t __argp_fmtstream_printf (argp_fmtstream_t __fs, | ||
132 | const char *__fmt, ...) | ||
133 | __attribute__ ((__format__ (printf, 2, 3))); | ||
134 | extern ssize_t argp_fmtstream_printf (argp_fmtstream_t __fs, | ||
135 | const char *__fmt, ...) | ||
136 | __attribute__ ((__format__ (printf, 2, 3))); | ||
137 | |||
138 | extern int __argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch); | ||
139 | extern int argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch); | ||
140 | |||
141 | extern int __argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str); | ||
142 | extern int argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str); | ||
143 | |||
144 | extern size_t __argp_fmtstream_write (argp_fmtstream_t __fs, | ||
145 | const char *__str, size_t __len); | ||
146 | extern size_t argp_fmtstream_write (argp_fmtstream_t __fs, | ||
147 | const char *__str, size_t __len); | ||
148 | |||
149 | /* Access macros for various bits of state. */ | ||
150 | #define argp_fmtstream_lmargin(__fs) ((__fs)->lmargin) | ||
151 | #define argp_fmtstream_rmargin(__fs) ((__fs)->rmargin) | ||
152 | #define argp_fmtstream_wmargin(__fs) ((__fs)->wmargin) | ||
153 | #define __argp_fmtstream_lmargin argp_fmtstream_lmargin | ||
154 | #define __argp_fmtstream_rmargin argp_fmtstream_rmargin | ||
155 | #define __argp_fmtstream_wmargin argp_fmtstream_wmargin | ||
156 | |||
157 | /* Set __FS's left margin to LMARGIN and return the old value. */ | ||
158 | extern size_t argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, | ||
159 | size_t __lmargin); | ||
160 | extern size_t __argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, | ||
161 | size_t __lmargin); | ||
162 | |||
163 | /* Set __FS's right margin to __RMARGIN and return the old value. */ | ||
164 | extern size_t argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, | ||
165 | size_t __rmargin); | ||
166 | extern size_t __argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, | ||
167 | size_t __rmargin); | ||
168 | |||
169 | /* Set __FS's wrap margin to __WMARGIN and return the old value. */ | ||
170 | extern size_t argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, | ||
171 | size_t __wmargin); | ||
172 | extern size_t __argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, | ||
173 | size_t __wmargin); | ||
174 | |||
175 | /* Return the column number of the current output point in __FS. */ | ||
176 | extern size_t argp_fmtstream_point (argp_fmtstream_t __fs); | ||
177 | extern size_t __argp_fmtstream_point (argp_fmtstream_t __fs); | ||
178 | |||
179 | /* Internal routines. */ | ||
180 | extern void _argp_fmtstream_update (argp_fmtstream_t __fs); | ||
181 | extern void __argp_fmtstream_update (argp_fmtstream_t __fs); | ||
182 | extern int _argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount); | ||
183 | extern int __argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount); | ||
184 | |||
185 | #ifdef __OPTIMIZE__ | ||
186 | /* Inline versions of above routines. */ | ||
187 | |||
188 | #if !_LIBC | ||
189 | #define __argp_fmtstream_putc argp_fmtstream_putc | ||
190 | #define __argp_fmtstream_puts argp_fmtstream_puts | ||
191 | #define __argp_fmtstream_write argp_fmtstream_write | ||
192 | #define __argp_fmtstream_set_lmargin argp_fmtstream_set_lmargin | ||
193 | #define __argp_fmtstream_set_rmargin argp_fmtstream_set_rmargin | ||
194 | #define __argp_fmtstream_set_wmargin argp_fmtstream_set_wmargin | ||
195 | #define __argp_fmtstream_point argp_fmtstream_point | ||
196 | #define __argp_fmtstream_update _argp_fmtstream_update | ||
197 | #define __argp_fmtstream_ensure _argp_fmtstream_ensure | ||
198 | #endif | ||
199 | |||
200 | #ifndef ARGP_FS_EI | ||
201 | #define ARGP_FS_EI extern inline | ||
202 | #endif | ||
203 | |||
204 | ARGP_FS_EI size_t | ||
205 | __argp_fmtstream_write (argp_fmtstream_t __fs, | ||
206 | const char *__str, size_t __len) | ||
207 | { | ||
208 | if (__fs->p + __len <= __fs->end || __argp_fmtstream_ensure (__fs, __len)) | ||
209 | { | ||
210 | memcpy (__fs->p, __str, __len); | ||
211 | __fs->p += __len; | ||
212 | return __len; | ||
213 | } | ||
214 | else | ||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | ARGP_FS_EI int | ||
219 | __argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str) | ||
220 | { | ||
221 | size_t __len = strlen (__str); | ||
222 | if (__len) | ||
223 | { | ||
224 | size_t __wrote = __argp_fmtstream_write (__fs, __str, __len); | ||
225 | return __wrote == __len ? 0 : -1; | ||
226 | } | ||
227 | else | ||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | ARGP_FS_EI int | ||
232 | __argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch) | ||
233 | { | ||
234 | if (__fs->p < __fs->end || __argp_fmtstream_ensure (__fs, 1)) | ||
235 | return *__fs->p++ = __ch; | ||
236 | else | ||
237 | return EOF; | ||
238 | } | ||
239 | |||
240 | /* Set __FS's left margin to __LMARGIN and return the old value. */ | ||
241 | ARGP_FS_EI size_t | ||
242 | __argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, size_t __lmargin) | ||
243 | { | ||
244 | size_t __old; | ||
245 | if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) | ||
246 | __argp_fmtstream_update (__fs); | ||
247 | __old = __fs->lmargin; | ||
248 | __fs->lmargin = __lmargin; | ||
249 | return __old; | ||
250 | } | ||
251 | |||
252 | /* Set __FS's right margin to __RMARGIN and return the old value. */ | ||
253 | ARGP_FS_EI size_t | ||
254 | __argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, size_t __rmargin) | ||
255 | { | ||
256 | size_t __old; | ||
257 | if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) | ||
258 | __argp_fmtstream_update (__fs); | ||
259 | __old = __fs->rmargin; | ||
260 | __fs->rmargin = __rmargin; | ||
261 | return __old; | ||
262 | } | ||
263 | |||
264 | /* Set FS's wrap margin to __WMARGIN and return the old value. */ | ||
265 | ARGP_FS_EI size_t | ||
266 | __argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, size_t __wmargin) | ||
267 | { | ||
268 | size_t __old; | ||
269 | if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) | ||
270 | __argp_fmtstream_update (__fs); | ||
271 | __old = __fs->wmargin; | ||
272 | __fs->wmargin = __wmargin; | ||
273 | return __old; | ||
274 | } | ||
275 | |||
276 | /* Return the column number of the current output point in __FS. */ | ||
277 | ARGP_FS_EI size_t | ||
278 | __argp_fmtstream_point (argp_fmtstream_t __fs) | ||
279 | { | ||
280 | if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) | ||
281 | __argp_fmtstream_update (__fs); | ||
282 | return __fs->point_col >= 0 ? __fs->point_col : 0; | ||
283 | } | ||
284 | |||
285 | #if !_LIBC | ||
286 | #undef __argp_fmtstream_putc | ||
287 | #undef __argp_fmtstream_puts | ||
288 | #undef __argp_fmtstream_write | ||
289 | #undef __argp_fmtstream_set_lmargin | ||
290 | #undef __argp_fmtstream_set_rmargin | ||
291 | #undef __argp_fmtstream_set_wmargin | ||
292 | #undef __argp_fmtstream_point | ||
293 | #undef __argp_fmtstream_update | ||
294 | #undef __argp_fmtstream_ensure | ||
295 | #endif | ||
296 | |||
297 | #endif /* __OPTIMIZE__ */ | ||
298 | |||
299 | #endif /* ARGP_FMTSTREAM_USE_LINEWRAP */ | ||
300 | |||
301 | #endif /* argp-fmtstream.h */ |
mailbox/argp-fs-xinl.c
deleted
100644 → 0
1 | /* Real definitions for extern inline functions in argp-fmtstream.h | ||
2 | Copyright (C) 1997, 2003, 2004 Free Software Foundation, Inc. | ||
3 | This file is part of the GNU C Library. | ||
4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. | ||
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 HAVE_CONFIG_H | ||
21 | # include <config.h> | ||
22 | #endif | ||
23 | |||
24 | #define ARGP_FS_EI | ||
25 | #undef __OPTIMIZE__ | ||
26 | #define __OPTIMIZE__ 1 | ||
27 | #include "argp-fmtstream.h" | ||
28 | |||
29 | #if 0 | ||
30 | /* Not exported. */ | ||
31 | /* Add weak aliases. */ | ||
32 | #if _LIBC - 0 && !defined (ARGP_FMTSTREAM_USE_LINEWRAP) && defined (weak_alias) | ||
33 | |||
34 | weak_alias (__argp_fmtstream_putc, argp_fmtstream_putc) | ||
35 | weak_alias (__argp_fmtstream_puts, argp_fmtstream_puts) | ||
36 | weak_alias (__argp_fmtstream_write, argp_fmtstream_write) | ||
37 | weak_alias (__argp_fmtstream_set_lmargin, argp_fmtstream_set_lmargin) | ||
38 | weak_alias (__argp_fmtstream_set_rmargin, argp_fmtstream_set_rmargin) | ||
39 | weak_alias (__argp_fmtstream_set_wmargin, argp_fmtstream_set_wmargin) | ||
40 | weak_alias (__argp_fmtstream_point, argp_fmtstream_point) | ||
41 | |||
42 | #endif | ||
43 | #endif |
mailbox/argp-help.c
deleted
100644 → 0
1 | /* Hierarchial argument parsing help output | ||
2 | Copyright (C) 1995-2003, 2004, 2005 Free Software Foundation, Inc. | ||
3 | This file is part of the GNU C Library. | ||
4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. | ||
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 _GNU_SOURCE | ||
21 | # define _GNU_SOURCE 1 | ||
22 | #endif | ||
23 | |||
24 | #ifdef HAVE_CONFIG_H | ||
25 | # include <config.h> | ||
26 | #endif | ||
27 | |||
28 | #include <alloca.h> | ||
29 | #include <errno.h> | ||
30 | #include <stddef.h> | ||
31 | #include <stdlib.h> | ||
32 | #include <string.h> | ||
33 | #include <assert.h> | ||
34 | #include <stdarg.h> | ||
35 | #include <ctype.h> | ||
36 | #include <limits.h> | ||
37 | #ifdef USE_IN_LIBIO | ||
38 | # include <wchar.h> | ||
39 | #endif | ||
40 | |||
41 | #ifdef _LIBC | ||
42 | # include <libintl.h> | ||
43 | # undef dgettext | ||
44 | # define dgettext(domain, msgid) \ | ||
45 | INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES) | ||
46 | #else | ||
47 | # include "gettext.h" | ||
48 | #endif | ||
49 | |||
50 | #include "argp.h" | ||
51 | #include "argp-fmtstream.h" | ||
52 | #include "argp-namefrob.h" | ||
53 | |||
54 | #ifndef SIZE_MAX | ||
55 | # define SIZE_MAX ((size_t) -1) | ||
56 | #endif | ||
57 | |||
58 | /* User-selectable (using an environment variable) formatting parameters. | ||
59 | |||
60 | These may be specified in an environment variable called `ARGP_HELP_FMT', | ||
61 | with a contents like: VAR1=VAL1,VAR2=VAL2,BOOLVAR2,no-BOOLVAR2 | ||
62 | Where VALn must be a positive integer. The list of variables is in the | ||
63 | UPARAM_NAMES vector, below. */ | ||
64 | |||
65 | /* Default parameters. */ | ||
66 | #define DUP_ARGS 0 /* True if option argument can be duplicated. */ | ||
67 | #define DUP_ARGS_NOTE 1 /* True to print a note about duplicate args. */ | ||
68 | #define SHORT_OPT_COL 2 /* column in which short options start */ | ||
69 | #define LONG_OPT_COL 6 /* column in which long options start */ | ||
70 | #define DOC_OPT_COL 2 /* column in which doc options start */ | ||
71 | #define OPT_DOC_COL 29 /* column in which option text starts */ | ||
72 | #define HEADER_COL 1 /* column in which group headers are printed */ | ||
73 | #define USAGE_INDENT 12 /* indentation of wrapped usage lines */ | ||
74 | #define RMARGIN 79 /* right margin used for wrapping */ | ||
75 | |||
76 | /* User-selectable (using an environment variable) formatting parameters. | ||
77 | They must all be of type `int' for the parsing code to work. */ | ||
78 | struct uparams | ||
79 | { | ||
80 | /* If true, arguments for an option are shown with both short and long | ||
81 | options, even when a given option has both, e.g. `-x ARG, --longx=ARG'. | ||
82 | If false, then if an option has both, the argument is only shown with | ||
83 | the long one, e.g., `-x, --longx=ARG', and a message indicating that | ||
84 | this really means both is printed below the options. */ | ||
85 | int dup_args; | ||
86 | |||
87 | /* This is true if when DUP_ARGS is false, and some duplicate arguments have | ||
88 | been suppressed, an explanatory message should be printed. */ | ||
89 | int dup_args_note; | ||
90 | |||
91 | /* Various output columns. */ | ||
92 | int short_opt_col; /* column in which short options start */ | ||
93 | int long_opt_col; /* column in which long options start */ | ||
94 | int doc_opt_col; /* column in which doc options start */ | ||
95 | int opt_doc_col; /* column in which option text starts */ | ||
96 | int header_col; /* column in which group headers are printed */ | ||
97 | int usage_indent; /* indentation of wrapped usage lines */ | ||
98 | int rmargin; /* right margin used for wrapping */ | ||
99 | |||
100 | int valid; /* True when the values in here are valid. */ | ||
101 | }; | ||
102 | |||
103 | /* This is a global variable, as user options are only ever read once. */ | ||
104 | static struct uparams uparams = { | ||
105 | DUP_ARGS, DUP_ARGS_NOTE, | ||
106 | SHORT_OPT_COL, LONG_OPT_COL, DOC_OPT_COL, OPT_DOC_COL, HEADER_COL, | ||
107 | USAGE_INDENT, RMARGIN, | ||
108 | 0 | ||
109 | }; | ||
110 | |||
111 | /* A particular uparam, and what the user name is. */ | ||
112 | struct uparam_name | ||
113 | { | ||
114 | const char *name; /* User name. */ | ||
115 | int is_bool; /* Whether it's `boolean'. */ | ||
116 | size_t uparams_offs; /* Location of the (int) field in UPARAMS. */ | ||
117 | }; | ||
118 | |||
119 | /* The name-field mappings we know about. */ | ||
120 | static const struct uparam_name uparam_names[] = | ||
121 | { | ||
122 | { "dup-args", 1, offsetof (struct uparams, dup_args) }, | ||
123 | { "dup-args-note", 1, offsetof (struct uparams, dup_args_note) }, | ||
124 | { "short-opt-col", 0, offsetof (struct uparams, short_opt_col) }, | ||
125 | { "long-opt-col", 0, offsetof (struct uparams, long_opt_col) }, | ||
126 | { "doc-opt-col", 0, offsetof (struct uparams, doc_opt_col) }, | ||
127 | { "opt-doc-col", 0, offsetof (struct uparams, opt_doc_col) }, | ||
128 | { "header-col", 0, offsetof (struct uparams, header_col) }, | ||
129 | { "usage-indent", 0, offsetof (struct uparams, usage_indent) }, | ||
130 | { "rmargin", 0, offsetof (struct uparams, rmargin) }, | ||
131 | { 0 } | ||
132 | }; | ||
133 | |||
134 | static void | ||
135 | validate_uparams (const struct argp_state *state, struct uparams *upptr) | ||
136 | { | ||
137 | const struct uparam_name *up; | ||
138 | |||
139 | for (up = uparam_names; up->name; up++) | ||
140 | { | ||
141 | if (up->is_bool | ||
142 | || up->uparams_offs == offsetof (struct uparams, rmargin)) | ||
143 | continue; | ||
144 | if (*(int *)((char *)upptr + up->uparams_offs) >= upptr->rmargin) | ||
145 | { | ||
146 | __argp_failure (state, 0, 0, | ||
147 | dgettext (state->root_argp->argp_domain, | ||
148 | "\ | ||
149 | ARGP_HELP_FMT: %s value is less than or equal to %s"), | ||
150 | "rmargin", up->name); | ||
151 | return; | ||
152 | } | ||
153 | } | ||
154 | uparams = *upptr; | ||
155 | uparams.valid = 1; | ||
156 | } | ||
157 | |||
158 | /* Read user options from the environment, and fill in UPARAMS appropiately. */ | ||
159 | static void | ||
160 | fill_in_uparams (const struct argp_state *state) | ||
161 | { | ||
162 | const char *var = getenv ("ARGP_HELP_FMT"); | ||
163 | struct uparams new_params = uparams; | ||
164 | |||
165 | #define SKIPWS(p) do { while (isspace (*p)) p++; } while (0); | ||
166 | |||
167 | if (var) | ||
168 | { | ||
169 | /* Parse var. */ | ||
170 | while (*var) | ||
171 | { | ||
172 | SKIPWS (var); | ||
173 | |||
174 | if (isalpha (*var)) | ||
175 | { | ||
176 | size_t var_len; | ||
177 | const struct uparam_name *un; | ||
178 | int unspec = 0, val = 0; | ||
179 | const char *arg = var; | ||
180 | |||
181 | while (isalnum (*arg) || *arg == '-' || *arg == '_') | ||
182 | arg++; | ||
183 | var_len = arg - var; | ||
184 | |||
185 | SKIPWS (arg); | ||
186 | |||
187 | if (*arg == '\0' || *arg == ',') | ||
188 | unspec = 1; | ||
189 | else if (*arg == '=') | ||
190 | { | ||
191 | arg++; | ||
192 | SKIPWS (arg); | ||
193 | } | ||
194 | |||
195 | if (unspec) | ||
196 | { | ||
197 | if (var[0] == 'n' && var[1] == 'o' && var[2] == '-') | ||
198 | { | ||
199 | val = 0; | ||
200 | var += 3; | ||
201 | var_len -= 3; | ||
202 | } | ||
203 | else | ||
204 | val = 1; | ||
205 | } | ||
206 | else if (isdigit (*arg)) | ||
207 | { | ||
208 | val = atoi (arg); | ||
209 | while (isdigit (*arg)) | ||
210 | arg++; | ||
211 | SKIPWS (arg); | ||
212 | } | ||
213 | |||
214 | for (un = uparam_names; un->name; un++) | ||
215 | if (strlen (un->name) == var_len | ||
216 | && strncmp (var, un->name, var_len) == 0) | ||
217 | { | ||
218 | if (unspec && !un->is_bool) | ||
219 | __argp_failure (state, 0, 0, | ||
220 | dgettext (state->root_argp->argp_domain, | ||
221 | "\ | ||
222 | %.*s: ARGP_HELP_FMT parameter requires a value"), | ||
223 | (int) var_len, var); | ||
224 | else if (val < 0) | ||
225 | __argp_failure (state, 0, 0, | ||
226 | dgettext (state->root_argp->argp_domain, | ||
227 | "\ | ||
228 | %.*s: ARGP_HELP_FMT parameter must be positive"), | ||
229 | (int) var_len, var); | ||
230 | else | ||
231 | *(int *)((char *)&new_params + un->uparams_offs) = val; | ||
232 | break; | ||
233 | } | ||
234 | if (! un->name) | ||
235 | __argp_failure (state, 0, 0, | ||
236 | dgettext (state->root_argp->argp_domain, "\ | ||
237 | %.*s: Unknown ARGP_HELP_FMT parameter"), | ||
238 | (int) var_len, var); | ||
239 | |||
240 | var = arg; | ||
241 | if (*var == ',') | ||
242 | var++; | ||
243 | } | ||
244 | else if (*var) | ||
245 | { | ||
246 | __argp_failure (state, 0, 0, | ||
247 | dgettext (state->root_argp->argp_domain, | ||
248 | "Garbage in ARGP_HELP_FMT: %s"), var); | ||
249 | break; | ||
250 | } | ||
251 | } | ||
252 | validate_uparams (state, &new_params); | ||
253 | } | ||
254 | } | ||
255 | |||
256 | /* Returns true if OPT hasn't been marked invisible. Visibility only affects | ||
257 | whether OPT is displayed or used in sorting, not option shadowing. */ | ||
258 | #define ovisible(opt) (! ((opt)->flags & OPTION_HIDDEN)) | ||
259 | |||
260 | /* Returns true if OPT is an alias for an earlier option. */ | ||
261 | #define oalias(opt) ((opt)->flags & OPTION_ALIAS) | ||
262 | |||
263 | /* Returns true if OPT is an documentation-only entry. */ | ||
264 | #define odoc(opt) ((opt)->flags & OPTION_DOC) | ||
265 | |||
266 | /* Returns true if OPT should not be translated */ | ||
267 | #define onotrans(opt) ((opt)->flags & OPTION_NO_TRANS) | ||
268 | |||
269 | /* Returns true if OPT is the end-of-list marker for a list of options. */ | ||
270 | #define oend(opt) __option_is_end (opt) | ||
271 | |||
272 | /* Returns true if OPT has a short option. */ | ||
273 | #define oshort(opt) __option_is_short (opt) | ||
274 | |||
275 | /* | ||
276 | The help format for a particular option is like: | ||
277 | |||
278 | -xARG, -yARG, --long1=ARG, --long2=ARG Documentation... | ||
279 | |||
280 | Where ARG will be omitted if there's no argument, for this option, or | ||
281 | will be surrounded by "[" and "]" appropiately if the argument is | ||
282 | optional. The documentation string is word-wrapped appropiately, and if | ||
283 | the list of options is long enough, it will be started on a separate line. | ||
284 | If there are no short options for a given option, the first long option is | ||
285 | indented slighly in a way that's supposed to make most long options appear | ||
286 | to be in a separate column. | ||
287 | |||
288 | For example, the following output (from ps): | ||
289 | |||
290 | -p PID, --pid=PID List the process PID | ||
291 | --pgrp=PGRP List processes in the process group PGRP | ||
292 | -P, -x, --no-parent Include processes without parents | ||
293 | -Q, --all-fields Don't elide unusable fields (normally if there's | ||
294 | some reason ps can't print a field for any | ||
295 | process, it's removed from the output entirely) | ||
296 | -r, --reverse, --gratuitously-long-reverse-option | ||
297 | Reverse the order of any sort | ||
298 | --session[=SID] Add the processes from the session SID (which | ||
299 | defaults to the sid of the current process) | ||
300 | |||
301 | Here are some more options: | ||
302 | -f ZOT, --foonly=ZOT Glork a foonly | ||
303 | -z, --zaza Snit a zar | ||
304 | |||
305 | -?, --help Give this help list | ||
306 | --usage Give a short usage message | ||
307 | -V, --version Print program version | ||
308 | |||
309 | The struct argp_option array for the above could look like: | ||
310 | |||
311 | { | ||
312 | {"pid", 'p', "PID", 0, "List the process PID"}, | ||
313 | {"pgrp", OPT_PGRP, "PGRP", 0, "List processes in the process group PGRP"}, | ||
314 | {"no-parent", 'P', 0, 0, "Include processes without parents"}, | ||
315 | {0, 'x', 0, OPTION_ALIAS}, | ||
316 | {"all-fields",'Q', 0, 0, "Don't elide unusable fields (normally" | ||
317 | " if there's some reason ps can't" | ||
318 | " print a field for any process, it's" | ||
319 | " removed from the output entirely)" }, | ||
320 | {"reverse", 'r', 0, 0, "Reverse the order of any sort"}, | ||
321 | {"gratuitously-long-reverse-option", 0, 0, OPTION_ALIAS}, | ||
322 | {"session", OPT_SESS, "SID", OPTION_ARG_OPTIONAL, | ||
323 | "Add the processes from the session" | ||
324 | " SID (which defaults to the sid of" | ||
325 | " the current process)" }, | ||
326 | |||
327 | {0,0,0,0, "Here are some more options:"}, | ||
328 | {"foonly", 'f', "ZOT", 0, "Glork a foonly"}, | ||
329 | {"zaza", 'z', 0, 0, "Snit a zar"}, | ||
330 | |||
331 | {0} | ||
332 | } | ||
333 | |||
334 | Note that the last three options are automatically supplied by argp_parse, | ||
335 | unless you tell it not to with ARGP_NO_HELP. | ||
336 | |||
337 | */ | ||
338 | |||
339 | /* Returns true if CH occurs between BEG and END. */ | ||
340 | static int | ||
341 | find_char (char ch, char *beg, char *end) | ||
342 | { | ||
343 | while (beg < end) | ||
344 | if (*beg == ch) | ||
345 | return 1; | ||
346 | else | ||
347 | beg++; | ||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | struct hol_cluster; /* fwd decl */ | ||
352 | |||
353 | struct hol_entry | ||
354 | { | ||
355 | /* First option. */ | ||
356 | const struct argp_option *opt; | ||
357 | /* Number of options (including aliases). */ | ||
358 | unsigned num; | ||
359 | |||
360 | /* A pointers into the HOL's short_options field, to the first short option | ||
361 | letter for this entry. The order of the characters following this point | ||
362 | corresponds to the order of options pointed to by OPT, and there are at | ||
363 | most NUM. A short option recorded in a option following OPT is only | ||
364 | valid if it occurs in the right place in SHORT_OPTIONS (otherwise it's | ||
365 | probably been shadowed by some other entry). */ | ||
366 | char *short_options; | ||
367 | |||
368 | /* Entries are sorted by their group first, in the order: | ||
369 | 1, 2, ..., n, 0, -m, ..., -2, -1 | ||
370 | and then alphabetically within each group. The default is 0. */ | ||
371 | int group; | ||
372 | |||
373 | /* The cluster of options this entry belongs to, or 0 if none. */ | ||
374 | struct hol_cluster *cluster; | ||
375 | |||
376 | /* The argp from which this option came. */ | ||
377 | const struct argp *argp; | ||
378 | }; | ||
379 | |||
380 | /* A cluster of entries to reflect the argp tree structure. */ | ||
381 | struct hol_cluster | ||
382 | { | ||
383 | /* A descriptive header printed before options in this cluster. */ | ||
384 | const char *header; | ||
385 | |||
386 | /* Used to order clusters within the same group with the same parent, | ||
387 | according to the order in which they occurred in the parent argp's child | ||
388 | list. */ | ||
389 | int index; | ||
390 | |||
391 | /* How to sort this cluster with respect to options and other clusters at the | ||
392 | same depth (clusters always follow options in the same group). */ | ||
393 | int group; | ||
394 | |||
395 | /* The cluster to which this cluster belongs, or 0 if it's at the base | ||
396 | level. */ | ||
397 | struct hol_cluster *parent; | ||
398 | |||
399 | /* The argp from which this cluster is (eventually) derived. */ | ||
400 | const struct argp *argp; | ||
401 | |||
402 | /* The distance this cluster is from the root. */ | ||
403 | int depth; | ||
404 | |||
405 | /* Clusters in a given hol are kept in a linked list, to make freeing them | ||
406 | possible. */ | ||
407 | struct hol_cluster *next; | ||
408 | }; | ||
409 | |||
410 | /* A list of options for help. */ | ||
411 | struct hol | ||
412 | { | ||
413 | /* An array of hol_entry's. */ | ||
414 | struct hol_entry *entries; | ||
415 | /* The number of entries in this hol. If this field is zero, the others | ||
416 | are undefined. */ | ||
417 | unsigned num_entries; | ||
418 | |||
419 | /* A string containing all short options in this HOL. Each entry contains | ||
420 | pointers into this string, so the order can't be messed with blindly. */ | ||
421 | char *short_options; | ||
422 | |||
423 | /* Clusters of entries in this hol. */ | ||
424 | struct hol_cluster *clusters; | ||
425 | }; | ||
426 | |||
427 | /* Create a struct hol from the options in ARGP. CLUSTER is the | ||
428 | hol_cluster in which these entries occur, or 0, if at the root. */ | ||
429 | static struct hol * | ||
430 | make_hol (const struct argp *argp, struct hol_cluster *cluster) | ||
431 | { | ||
432 | char *so; | ||
433 | const struct argp_option *o; | ||
434 | const struct argp_option *opts = argp->options; | ||
435 | struct hol_entry *entry; | ||
436 | unsigned num_short_options = 0; | ||
437 | struct hol *hol = malloc (sizeof (struct hol)); | ||
438 | |||
439 | assert (hol); | ||
440 | |||
441 | hol->num_entries = 0; | ||
442 | hol->clusters = 0; | ||
443 | |||
444 | if (opts) | ||
445 | { | ||
446 | int cur_group = 0; | ||
447 | |||
448 | /* The first option must not be an alias. */ | ||
449 | assert (! oalias (opts)); | ||
450 | |||
451 | /* Calculate the space needed. */ | ||
452 | for (o = opts; ! oend (o); o++) | ||
453 | { | ||
454 | if (! oalias (o)) | ||
455 | hol->num_entries++; | ||
456 | if (oshort (o)) | ||
457 | num_short_options++; /* This is an upper bound. */ | ||
458 | } | ||
459 | |||
460 | hol->entries = malloc (sizeof (struct hol_entry) * hol->num_entries); | ||
461 | hol->short_options = malloc (num_short_options + 1); | ||
462 | |||
463 | assert (hol->entries && hol->short_options); | ||
464 | if (SIZE_MAX <= UINT_MAX) | ||
465 | assert (hol->num_entries <= SIZE_MAX / sizeof (struct hol_entry)); | ||
466 | |||
467 | /* Fill in the entries. */ | ||
468 | so = hol->short_options; | ||
469 | for (o = opts, entry = hol->entries; ! oend (o); entry++) | ||
470 | { | ||
471 | entry->opt = o; | ||
472 | entry->num = 0; | ||
473 | entry->short_options = so; | ||
474 | entry->group = cur_group = | ||
475 | o->group | ||
476 | ? o->group | ||
477 | : ((!o->name && !o->key) | ||
478 | ? cur_group + 1 | ||
479 | : cur_group); | ||
480 | entry->cluster = cluster; | ||
481 | entry->argp = argp; | ||
482 | |||
483 | do | ||
484 | { | ||
485 | entry->num++; | ||
486 | if (oshort (o) && ! find_char (o->key, hol->short_options, so)) | ||
487 | /* O has a valid short option which hasn't already been used.*/ | ||
488 | *so++ = o->key; | ||
489 | o++; | ||
490 | } | ||
491 | while (! oend (o) && oalias (o)); | ||
492 | } | ||
493 | *so = '\0'; /* null terminated so we can find the length */ | ||
494 | } | ||
495 | |||
496 | return hol; | ||
497 | } | ||
498 | |||
499 | /* Add a new cluster to HOL, with the given GROUP and HEADER (taken from the | ||
500 | associated argp child list entry), INDEX, and PARENT, and return a pointer | ||
501 | to it. ARGP is the argp that this cluster results from. */ | ||
502 | static struct hol_cluster * | ||
503 | hol_add_cluster (struct hol *hol, int group, const char *header, int index, | ||
504 | struct hol_cluster *parent, const struct argp *argp) | ||
505 | { | ||
506 | struct hol_cluster *cl = malloc (sizeof (struct hol_cluster)); | ||
507 | if (cl) | ||
508 | { | ||
509 | cl->group = group; | ||
510 | cl->header = header; | ||
511 | |||
512 | cl->index = index; | ||
513 | cl->parent = parent; | ||
514 | cl->argp = argp; | ||
515 | cl->depth = parent ? parent->depth + 1 : 0; | ||
516 | |||
517 | cl->next = hol->clusters; | ||
518 | hol->clusters = cl; | ||
519 | } | ||
520 | return cl; | ||
521 | } | ||
522 | |||
523 | /* Free HOL and any resources it uses. */ | ||
524 | static void | ||
525 | hol_free (struct hol *hol) | ||
526 | { | ||
527 | struct hol_cluster *cl = hol->clusters; | ||
528 | |||
529 | while (cl) | ||
530 | { | ||
531 | struct hol_cluster *next = cl->next; | ||
532 | free (cl); | ||
533 | cl = next; | ||
534 | } | ||
535 | |||
536 | if (hol->num_entries > 0) | ||
537 | { | ||
538 | free (hol->entries); | ||
539 | free (hol->short_options); | ||
540 | } | ||
541 | |||
542 | free (hol); | ||
543 | } | ||
544 | |||
545 | static int | ||
546 | hol_entry_short_iterate (const struct hol_entry *entry, | ||
547 | int (*func)(const struct argp_option *opt, | ||
548 | const struct argp_option *real, | ||
549 | const char *domain, void *cookie), | ||
550 | const char *domain, void *cookie) | ||
551 | { | ||
552 | unsigned nopts; | ||
553 | int val = 0; | ||
554 | const struct argp_option *opt, *real = entry->opt; | ||
555 | char *so = entry->short_options; | ||
556 | |||
557 | for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--) | ||
558 | if (oshort (opt) && *so == opt->key) | ||
559 | { | ||
560 | if (!oalias (opt)) | ||
561 | real = opt; | ||
562 | if (ovisible (opt)) | ||
563 | val = (*func)(opt, real, domain, cookie); | ||
564 | so++; | ||
565 | } | ||
566 | |||
567 | return val; | ||
568 | } | ||
569 | |||
570 | static inline int | ||
571 | __attribute__ ((always_inline)) | ||
572 | hol_entry_long_iterate (const struct hol_entry *entry, | ||
573 | int (*func)(const struct argp_option *opt, | ||
574 | const struct argp_option *real, | ||
575 | const char *domain, void *cookie), | ||
576 | const char *domain, void *cookie) | ||
577 | { | ||
578 | unsigned nopts; | ||
579 | int val = 0; | ||
580 | const struct argp_option *opt, *real = entry->opt; | ||
581 | |||
582 | for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--) | ||
583 | if (opt->name) | ||
584 | { | ||
585 | if (!oalias (opt)) | ||
586 | real = opt; | ||
587 | if (ovisible (opt)) | ||
588 | val = (*func)(opt, real, domain, cookie); | ||
589 | } | ||
590 | |||
591 | return val; | ||
592 | } | ||
593 | |||
594 | /* Iterator that returns true for the first short option. */ | ||
595 | static inline int | ||
596 | until_short (const struct argp_option *opt, const struct argp_option *real, | ||
597 | const char *domain, void *cookie) | ||
598 | { | ||
599 | return oshort (opt) ? opt->key : 0; | ||
600 | } | ||
601 | |||
602 | /* Returns the first valid short option in ENTRY, or 0 if there is none. */ | ||
603 | static char | ||
604 | hol_entry_first_short (const struct hol_entry *entry) | ||
605 | { | ||
606 | return hol_entry_short_iterate (entry, until_short, | ||
607 | entry->argp->argp_domain, 0); | ||
608 | } | ||
609 | |||
610 | /* Returns the first valid long option in ENTRY, or 0 if there is none. */ | ||
611 | static const char * | ||
612 | hol_entry_first_long (const struct hol_entry *entry) | ||
613 | { | ||
614 | const struct argp_option *opt; | ||
615 | unsigned num; | ||
616 | for (opt = entry->opt, num = entry->num; num > 0; opt++, num--) | ||
617 | if (opt->name && ovisible (opt)) | ||
618 | return opt->name; | ||
619 | return 0; | ||
620 | } | ||
621 | |||
622 | /* Returns the entry in HOL with the long option name NAME, or 0 if there is | ||
623 | none. */ | ||
624 | static struct hol_entry * | ||
625 | hol_find_entry (struct hol *hol, const char *name) | ||
626 | { | ||
627 | struct hol_entry *entry = hol->entries; | ||
628 | unsigned num_entries = hol->num_entries; | ||
629 | |||
630 | while (num_entries-- > 0) | ||
631 | { | ||
632 | const struct argp_option *opt = entry->opt; | ||
633 | unsigned num_opts = entry->num; | ||
634 | |||
635 | while (num_opts-- > 0) | ||
636 | if (opt->name && ovisible (opt) && strcmp (opt->name, name) == 0) | ||
637 | return entry; | ||
638 | else | ||
639 | opt++; | ||
640 | |||
641 | entry++; | ||
642 | } | ||
643 | |||
644 | return 0; | ||
645 | } | ||
646 | |||
647 | /* If an entry with the long option NAME occurs in HOL, set it's special | ||
648 | sort position to GROUP. */ | ||
649 | static void | ||
650 | hol_set_group (struct hol *hol, const char *name, int group) | ||
651 | { | ||
652 | struct hol_entry *entry = hol_find_entry (hol, name); | ||
653 | if (entry) | ||
654 | entry->group = group; | ||
655 | } | ||
656 | |||
657 | /* Order by group: 0, 1, 2, ..., n, -m, ..., -2, -1. | ||
658 | EQ is what to return if GROUP1 and GROUP2 are the same. */ | ||
659 | static int | ||
660 | group_cmp (int group1, int group2, int eq) | ||
661 | { | ||
662 | if (group1 == group2) | ||
663 | return eq; | ||
664 | else if ((group1 < 0 && group2 < 0) || (group1 >= 0 && group2 >= 0)) | ||
665 | return group1 - group2; | ||
666 | else | ||
667 | return group2 - group1; | ||
668 | } | ||
669 | |||
670 | /* Compare clusters CL1 & CL2 by the order that they should appear in | ||
671 | output. */ | ||
672 | static int | ||
673 | hol_cluster_cmp (const struct hol_cluster *cl1, const struct hol_cluster *cl2) | ||
674 | { | ||
675 | /* If one cluster is deeper than the other, use its ancestor at the same | ||
676 | level, so that finding the common ancestor is straightforward. */ | ||
677 | while (cl1->depth < cl2->depth) | ||
678 | cl1 = cl1->parent; | ||
679 | while (cl2->depth < cl1->depth) | ||
680 | cl2 = cl2->parent; | ||
681 | |||
682 | /* Now reduce both clusters to their ancestors at the point where both have | ||
683 | a common parent; these can be directly compared. */ | ||
684 | while (cl1->parent != cl2->parent) | ||
685 | cl1 = cl1->parent, cl2 = cl2->parent; | ||
686 | |||
687 | return group_cmp (cl1->group, cl2->group, cl2->index - cl1->index); | ||
688 | } | ||
689 | |||
690 | /* Return the ancestor of CL that's just below the root (i.e., has a parent | ||
691 | of 0). */ | ||
692 | static struct hol_cluster * | ||
693 | hol_cluster_base (struct hol_cluster *cl) | ||
694 | { | ||
695 | while (cl->parent) | ||
696 | cl = cl->parent; | ||
697 | return cl; | ||
698 | } | ||
699 | |||
700 | /* Return true if CL1 is a child of CL2. */ | ||
701 | static int | ||
702 | hol_cluster_is_child (const struct hol_cluster *cl1, | ||
703 | const struct hol_cluster *cl2) | ||
704 | { | ||
705 | while (cl1 && cl1 != cl2) | ||
706 | cl1 = cl1->parent; | ||
707 | return cl1 == cl2; | ||
708 | } | ||
709 | |||
710 | /* Given the name of a OPTION_DOC option, modifies NAME to start at the tail | ||
711 | that should be used for comparisons, and returns true iff it should be | ||
712 | treated as a non-option. */ | ||
713 | static int | ||
714 | canon_doc_option (const char **name) | ||
715 | { | ||
716 | int non_opt; | ||
717 | |||
718 | if (!*name) | ||
719 | non_opt = 1; | ||
720 | else | ||
721 | { | ||
722 | /* Skip initial whitespace. */ | ||
723 | while (isspace (**name)) | ||
724 | (*name)++; | ||
725 | /* Decide whether this looks like an option (leading `-') or not. */ | ||
726 | non_opt = (**name != '-'); | ||
727 | /* Skip until part of name used for sorting. */ | ||
728 | while (**name && !isalnum (**name)) | ||
729 | (*name)++; | ||
730 | } | ||
731 | return non_opt; | ||
732 | } | ||
733 | |||
734 | /* Order ENTRY1 & ENTRY2 by the order which they should appear in a help | ||
735 | listing. */ | ||
736 | static int | ||
737 | hol_entry_cmp (const struct hol_entry *entry1, | ||
738 | const struct hol_entry *entry2) | ||
739 | { | ||
740 | /* The group numbers by which the entries should be ordered; if either is | ||
741 | in a cluster, then this is just the group within the cluster. */ | ||
742 | int group1 = entry1->group, group2 = entry2->group; | ||
743 | |||
744 | if (entry1->cluster != entry2->cluster) | ||
745 | { | ||
746 | /* The entries are not within the same cluster, so we can't compare them | ||
747 | directly, we have to use the appropiate clustering level too. */ | ||
748 | if (! entry1->cluster) | ||
749 | /* ENTRY1 is at the `base level', not in a cluster, so we have to | ||
750 | compare it's group number with that of the base cluster in which | ||
751 | ENTRY2 resides. Note that if they're in the same group, the | ||
752 | clustered option always comes laster. */ | ||
753 | return group_cmp (group1, hol_cluster_base (entry2->cluster)->group, -1); | ||
754 | else if (! entry2->cluster) | ||
755 | /* Likewise, but ENTRY2's not in a cluster. */ | ||
756 | return group_cmp (hol_cluster_base (entry1->cluster)->group, group2, 1); | ||
757 | else | ||
758 | /* Both entries are in clusters, we can just compare the clusters. */ | ||
759 | return hol_cluster_cmp (entry1->cluster, entry2->cluster); | ||
760 | } | ||
761 | else if (group1 == group2) | ||
762 | /* The entries are both in the same cluster and group, so compare them | ||
763 | alphabetically. */ | ||
764 | { | ||
765 | int short1 = hol_entry_first_short (entry1); | ||
766 | int short2 = hol_entry_first_short (entry2); | ||
767 | int doc1 = odoc (entry1->opt); | ||
768 | int doc2 = odoc (entry2->opt); | ||
769 | const char *long1 = hol_entry_first_long (entry1); | ||
770 | const char *long2 = hol_entry_first_long (entry2); | ||
771 | |||
772 | if (doc1) | ||
773 | doc1 = canon_doc_option (&long1); | ||
774 | if (doc2) | ||
775 | doc2 = canon_doc_option (&long2); | ||
776 | |||
777 | if (doc1 != doc2) | ||
778 | /* `documentation' options always follow normal options (or | ||
779 | documentation options that *look* like normal options). */ | ||
780 | return doc1 - doc2; | ||
781 | else if (!short1 && !short2 && long1 && long2) | ||
782 | /* Only long options. */ | ||
783 | return __strcasecmp (long1, long2); | ||
784 | else | ||
785 | /* Compare short/short, long/short, short/long, using the first | ||
786 | character of long options. Entries without *any* valid | ||
787 | options (such as options with OPTION_HIDDEN set) will be put | ||
788 | first, but as they're not displayed, it doesn't matter where | ||
789 | they are. */ | ||
790 | { | ||
791 | char first1 = short1 ? short1 : long1 ? *long1 : 0; | ||
792 | char first2 = short2 ? short2 : long2 ? *long2 : 0; | ||
793 | #ifdef _tolower | ||
794 | int lower_cmp = _tolower (first1) - _tolower (first2); | ||
795 | #else | ||
796 | int lower_cmp = tolower (first1) - tolower (first2); | ||
797 | #endif | ||
798 | /* Compare ignoring case, except when the options are both the | ||
799 | same letter, in which case lower-case always comes first. */ | ||
800 | return lower_cmp ? lower_cmp : first2 - first1; | ||
801 | } | ||
802 | } | ||
803 | else | ||
804 | /* Within the same cluster, but not the same group, so just compare | ||
805 | groups. */ | ||
806 | return group_cmp (group1, group2, 0); | ||
807 | } | ||
808 | |||
809 | /* Version of hol_entry_cmp with correct signature for qsort. */ | ||
810 | static int | ||
811 | hol_entry_qcmp (const void *entry1_v, const void *entry2_v) | ||
812 | { | ||
813 | return hol_entry_cmp (entry1_v, entry2_v); | ||
814 | } | ||
815 | |||
816 | /* Sort HOL by group and alphabetically by option name (with short options | ||
817 | taking precedence over long). Since the sorting is for display purposes | ||
818 | only, the shadowing of options isn't effected. */ | ||
819 | static void | ||
820 | hol_sort (struct hol *hol) | ||
821 | { | ||
822 | if (hol->num_entries > 0) | ||
823 | qsort (hol->entries, hol->num_entries, sizeof (struct hol_entry), | ||
824 | hol_entry_qcmp); | ||
825 | } | ||
826 | |||
827 | /* Append MORE to HOL, destroying MORE in the process. Options in HOL shadow | ||
828 | any in MORE with the same name. */ | ||
829 | static void | ||
830 | hol_append (struct hol *hol, struct hol *more) | ||
831 | { | ||
832 | struct hol_cluster **cl_end = &hol->clusters; | ||
833 | |||
834 | /* Steal MORE's cluster list, and add it to the end of HOL's. */ | ||
835 | while (*cl_end) | ||
836 | cl_end = &(*cl_end)->next; | ||
837 | *cl_end = more->clusters; | ||
838 | more->clusters = 0; | ||
839 | |||
840 | /* Merge entries. */ | ||
841 | if (more->num_entries > 0) | ||
842 | { | ||
843 | if (hol->num_entries == 0) | ||
844 | { | ||
845 | hol->num_entries = more->num_entries; | ||
846 | hol->entries = more->entries; | ||
847 | hol->short_options = more->short_options; | ||
848 | more->num_entries = 0; /* Mark MORE's fields as invalid. */ | ||
849 | } | ||
850 | else | ||
851 | /* Append the entries in MORE to those in HOL, taking care to only add | ||
852 | non-shadowed SHORT_OPTIONS values. */ | ||
853 | { | ||
854 | unsigned left; | ||
855 | char *so, *more_so; | ||
856 | struct hol_entry *e; | ||
857 | unsigned num_entries = hol->num_entries + more->num_entries; | ||
858 | struct hol_entry *entries = | ||
859 | malloc (num_entries * sizeof (struct hol_entry)); | ||
860 | unsigned hol_so_len = strlen (hol->short_options); | ||
861 | char *short_options = | ||
862 | malloc (hol_so_len + strlen (more->short_options) + 1); | ||
863 | |||
864 | assert (entries && short_options); | ||
865 | if (SIZE_MAX <= UINT_MAX) | ||
866 | assert (num_entries <= SIZE_MAX / sizeof (struct hol_entry)); | ||
867 | |||
868 | __mempcpy (__mempcpy (entries, hol->entries, | ||
869 | hol->num_entries * sizeof (struct hol_entry)), | ||
870 | more->entries, | ||
871 | more->num_entries * sizeof (struct hol_entry)); | ||
872 | |||
873 | __mempcpy (short_options, hol->short_options, hol_so_len); | ||
874 | |||
875 | /* Fix up the short options pointers from HOL. */ | ||
876 | for (e = entries, left = hol->num_entries; left > 0; e++, left--) | ||
877 | e->short_options += (short_options - hol->short_options); | ||
878 | |||
879 | /* Now add the short options from MORE, fixing up its entries | ||
880 | too. */ | ||
881 | so = short_options + hol_so_len; | ||
882 | more_so = more->short_options; | ||
883 | for (left = more->num_entries; left > 0; e++, left--) | ||
884 | { | ||
885 | int opts_left; | ||
886 | const struct argp_option *opt; | ||
887 | |||
888 | e->short_options = so; | ||
889 | |||
890 | for (opts_left = e->num, opt = e->opt; opts_left; opt++, opts_left--) | ||
891 | { | ||
892 | int ch = *more_so; | ||
893 | if (oshort (opt) && ch == opt->key) | ||
894 | /* The next short option in MORE_SO, CH, is from OPT. */ | ||
895 | { | ||
896 | if (! find_char (ch, short_options, | ||
897 | short_options + hol_so_len)) | ||
898 | /* The short option CH isn't shadowed by HOL's options, | ||
899 | so add it to the sum. */ | ||
900 | *so++ = ch; | ||
901 | more_so++; | ||
902 | } | ||
903 | } | ||
904 | } | ||
905 | |||
906 | *so = '\0'; | ||
907 | |||
908 | free (hol->entries); | ||
909 | free (hol->short_options); | ||
910 | |||
911 | hol->entries = entries; | ||
912 | hol->num_entries = num_entries; | ||
913 | hol->short_options = short_options; | ||
914 | } | ||
915 | } | ||
916 | |||
917 | hol_free (more); | ||
918 | } | ||
919 | |||
920 | /* Inserts enough spaces to make sure STREAM is at column COL. */ | ||
921 | static void | ||
922 | indent_to (argp_fmtstream_t stream, unsigned col) | ||
923 | { | ||
924 | int needed = col - __argp_fmtstream_point (stream); | ||
925 | while (needed-- > 0) | ||
926 | __argp_fmtstream_putc (stream, ' '); | ||
927 | } | ||
928 | |||
929 | /* Output to STREAM either a space, or a newline if there isn't room for at | ||
930 | least ENSURE characters before the right margin. */ | ||
931 | static void | ||
932 | space (argp_fmtstream_t stream, size_t ensure) | ||
933 | { | ||
934 | if (__argp_fmtstream_point (stream) + ensure | ||
935 | >= __argp_fmtstream_rmargin (stream)) | ||
936 | __argp_fmtstream_putc (stream, '\n'); | ||
937 | else | ||
938 | __argp_fmtstream_putc (stream, ' '); | ||
939 | } | ||
940 | |||
941 | /* If the option REAL has an argument, we print it in using the printf | ||
942 | format REQ_FMT or OPT_FMT depending on whether it's a required or | ||
943 | optional argument. */ | ||
944 | static void | ||
945 | arg (const struct argp_option *real, const char *req_fmt, const char *opt_fmt, | ||
946 | const char *domain, argp_fmtstream_t stream) | ||
947 | { | ||
948 | if (real->arg) | ||
949 | { | ||
950 | if (real->flags & OPTION_ARG_OPTIONAL) | ||
951 | __argp_fmtstream_printf (stream, opt_fmt, | ||
952 | dgettext (domain, real->arg)); | ||
953 | else | ||
954 | __argp_fmtstream_printf (stream, req_fmt, | ||
955 | dgettext (domain, real->arg)); | ||
956 | } | ||
957 | } | ||
958 | |||
959 | /* Helper functions for hol_entry_help. */ | ||
960 | |||
961 | /* State used during the execution of hol_help. */ | ||
962 | struct hol_help_state | ||
963 | { | ||
964 | /* PREV_ENTRY should contain the previous entry printed, or 0. */ | ||
965 | struct hol_entry *prev_entry; | ||
966 | |||
967 | /* If an entry is in a different group from the previous one, and SEP_GROUPS | ||
968 | is true, then a blank line will be printed before any output. */ | ||
969 | int sep_groups; | ||
970 | |||
971 | /* True if a duplicate option argument was suppressed (only ever set if | ||
972 | UPARAMS.dup_args is false). */ | ||
973 | int suppressed_dup_arg; | ||
974 | }; | ||
975 | |||
976 | /* Some state used while printing a help entry (used to communicate with | ||
977 | helper functions). See the doc for hol_entry_help for more info, as most | ||
978 | of the fields are copied from its arguments. */ | ||
979 | struct pentry_state | ||
980 | { | ||
981 | const struct hol_entry *entry; | ||
982 | argp_fmtstream_t stream; | ||
983 | struct hol_help_state *hhstate; | ||
984 | |||
985 | /* True if nothing's been printed so far. */ | ||
986 | int first; | ||
987 | |||
988 | /* If non-zero, the state that was used to print this help. */ | ||
989 | const struct argp_state *state; | ||
990 | }; | ||
991 | |||
992 | /* If a user doc filter should be applied to DOC, do so. */ | ||
993 | static const char * | ||
994 | filter_doc (const char *doc, int key, const struct argp *argp, | ||
995 | const struct argp_state *state) | ||
996 | { | ||
997 | if (argp->help_filter) | ||
998 | /* We must apply a user filter to this output. */ | ||
999 | { | ||
1000 | void *input = __argp_input (argp, state); | ||
1001 | return (*argp->help_filter) (key, doc, input); | ||
1002 | } | ||
1003 | else | ||
1004 | /* No filter. */ | ||
1005 | return doc; | ||
1006 | } | ||
1007 | |||
1008 | /* Prints STR as a header line, with the margin lines set appropiately, and | ||
1009 | notes the fact that groups should be separated with a blank line. ARGP is | ||
1010 | the argp that should dictate any user doc filtering to take place. Note | ||
1011 | that the previous wrap margin isn't restored, but the left margin is reset | ||
1012 | to 0. */ | ||
1013 | static void | ||
1014 | print_header (const char *str, const struct argp *argp, | ||
1015 | struct pentry_state *pest) | ||
1016 | { | ||
1017 | const char *tstr = dgettext (argp->argp_domain, str); | ||
1018 | const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_HEADER, argp, pest->state); | ||
1019 | |||
1020 | if (fstr) | ||
1021 | { | ||
1022 | if (*fstr) | ||
1023 | { | ||
1024 | if (pest->hhstate->prev_entry) | ||
1025 | /* Precede with a blank line. */ | ||
1026 | __argp_fmtstream_putc (pest->stream, '\n'); | ||
1027 | indent_to (pest->stream, uparams.header_col); | ||
1028 | __argp_fmtstream_set_lmargin (pest->stream, uparams.header_col); | ||
1029 | __argp_fmtstream_set_wmargin (pest->stream, uparams.header_col); | ||
1030 | __argp_fmtstream_puts (pest->stream, fstr); | ||
1031 | __argp_fmtstream_set_lmargin (pest->stream, 0); | ||
1032 | __argp_fmtstream_putc (pest->stream, '\n'); | ||
1033 | } | ||
1034 | |||
1035 | pest->hhstate->sep_groups = 1; /* Separate subsequent groups. */ | ||
1036 | } | ||
1037 | |||
1038 | if (fstr != tstr) | ||
1039 | free ((char *) fstr); | ||
1040 | } | ||
1041 | |||
1042 | /* Inserts a comma if this isn't the first item on the line, and then makes | ||
1043 | sure we're at least to column COL. If this *is* the first item on a line, | ||
1044 | prints any pending whitespace/headers that should precede this line. Also | ||
1045 | clears FIRST. */ | ||
1046 | static void | ||
1047 | comma (unsigned col, struct pentry_state *pest) | ||
1048 | { | ||
1049 | if (pest->first) | ||
1050 | { | ||
1051 | const struct hol_entry *pe = pest->hhstate->prev_entry; | ||
1052 | const struct hol_cluster *cl = pest->entry->cluster; | ||
1053 | |||
1054 | if (pest->hhstate->sep_groups && pe && pest->entry->group != pe->group) | ||
1055 | __argp_fmtstream_putc (pest->stream, '\n'); | ||
1056 | |||
1057 | if (cl && cl->header && *cl->header | ||
1058 | && (!pe | ||
1059 | || (pe->cluster != cl | ||
1060 | && !hol_cluster_is_child (pe->cluster, cl)))) | ||
1061 | /* If we're changing clusters, then this must be the start of the | ||
1062 | ENTRY's cluster unless that is an ancestor of the previous one | ||
1063 | (in which case we had just popped into a sub-cluster for a bit). | ||
1064 | If so, then print the cluster's header line. */ | ||
1065 | { | ||
1066 | int old_wm = __argp_fmtstream_wmargin (pest->stream); | ||
1067 | print_header (cl->header, cl->argp, pest); | ||
1068 | __argp_fmtstream_set_wmargin (pest->stream, old_wm); | ||
1069 | } | ||
1070 | |||
1071 | pest->first = 0; | ||
1072 | } | ||
1073 | else | ||
1074 | __argp_fmtstream_puts (pest->stream, ", "); | ||
1075 | |||
1076 | indent_to (pest->stream, col); | ||
1077 | } | ||
1078 | |||
1079 | /* Print help for ENTRY to STREAM. */ | ||
1080 | static void | ||
1081 | hol_entry_help (struct hol_entry *entry, const struct argp_state *state, | ||
1082 | argp_fmtstream_t stream, struct hol_help_state *hhstate) | ||
1083 | { | ||
1084 | unsigned num; | ||
1085 | const struct argp_option *real = entry->opt, *opt; | ||
1086 | char *so = entry->short_options; | ||
1087 | int have_long_opt = 0; /* We have any long options. */ | ||
1088 | /* Saved margins. */ | ||
1089 | int old_lm = __argp_fmtstream_set_lmargin (stream, 0); | ||
1090 | int old_wm = __argp_fmtstream_wmargin (stream); | ||
1091 | /* PEST is a state block holding some of our variables that we'd like to | ||
1092 | share with helper functions. */ | ||
1093 | struct pentry_state pest; | ||
1094 | |||
1095 | pest.entry = entry; | ||
1096 | pest.stream = stream; | ||
1097 | pest.hhstate = hhstate; | ||
1098 | pest.first = 1; | ||
1099 | pest.state = state; | ||
1100 | |||
1101 | if (! odoc (real)) | ||
1102 | for (opt = real, num = entry->num; num > 0; opt++, num--) | ||
1103 | if (opt->name && ovisible (opt)) | ||
1104 | { | ||
1105 | have_long_opt = 1; | ||
1106 | break; | ||
1107 | } | ||
1108 | |||
1109 | /* First emit short options. */ | ||
1110 | __argp_fmtstream_set_wmargin (stream, uparams.short_opt_col); /* For truly bizarre cases. */ | ||
1111 | for (opt = real, num = entry->num; num > 0; opt++, num--) | ||
1112 | if (oshort (opt) && opt->key == *so) | ||
1113 | /* OPT has a valid (non shadowed) short option. */ | ||
1114 | { | ||
1115 | if (ovisible (opt)) | ||
1116 | { | ||
1117 | comma (uparams.short_opt_col, &pest); | ||
1118 | __argp_fmtstream_putc (stream, '-'); | ||
1119 | __argp_fmtstream_putc (stream, *so); | ||
1120 | if (!have_long_opt || uparams.dup_args) | ||
1121 | arg (real, " %s", "[%s]", state->root_argp->argp_domain, stream); | ||
1122 | else if (real->arg) | ||
1123 | hhstate->suppressed_dup_arg = 1; | ||
1124 | } | ||
1125 | so++; | ||
1126 | } | ||
1127 | |||
1128 | /* Now, long options. */ | ||
1129 | if (odoc (real)) | ||
1130 | /* A `documentation' option. */ | ||
1131 | { | ||
1132 | __argp_fmtstream_set_wmargin (stream, uparams.doc_opt_col); | ||
1133 | for (opt = real, num = entry->num; num > 0; opt++, num--) | ||
1134 | if (opt->name && *opt->name && ovisible (opt)) | ||
1135 | { | ||
1136 | comma (uparams.doc_opt_col, &pest); | ||
1137 | /* Calling dgettext here isn't quite right, since sorting will | ||
1138 | have been done on the original; but documentation options | ||
1139 | should be pretty rare anyway... */ | ||
1140 | __argp_fmtstream_puts (stream, | ||
1141 | onotrans (opt) ? | ||
1142 | opt->name : | ||
1143 | dgettext (state->root_argp->argp_domain, | ||
1144 | opt->name)); | ||
1145 | } | ||
1146 | } | ||
1147 | else | ||
1148 | /* A real long option. */ | ||
1149 | { | ||
1150 | int first_long_opt = 1; | ||
1151 | |||
1152 | __argp_fmtstream_set_wmargin (stream, uparams.long_opt_col); | ||
1153 | for (opt = real, num = entry->num; num > 0; opt++, num--) | ||
1154 | if (opt->name && ovisible (opt)) | ||
1155 | { | ||
1156 | comma (uparams.long_opt_col, &pest); | ||
1157 | __argp_fmtstream_printf (stream, "--%s", opt->name); | ||
1158 | if (first_long_opt || uparams.dup_args) | ||
1159 | arg (real, "=%s", "[=%s]", state->root_argp->argp_domain, | ||
1160 | stream); | ||
1161 | else if (real->arg) | ||
1162 | hhstate->suppressed_dup_arg = 1; | ||
1163 | } | ||
1164 | } | ||
1165 | |||
1166 | /* Next, documentation strings. */ | ||
1167 | __argp_fmtstream_set_lmargin (stream, 0); | ||
1168 | |||
1169 | if (pest.first) | ||
1170 | { | ||
1171 | /* Didn't print any switches, what's up? */ | ||
1172 | if (!oshort (real) && !real->name) | ||
1173 | /* This is a group header, print it nicely. */ | ||
1174 | print_header (real->doc, entry->argp, &pest); | ||
1175 | else | ||
1176 | /* Just a totally shadowed option or null header; print nothing. */ | ||
1177 | goto cleanup; /* Just return, after cleaning up. */ | ||
1178 | } | ||
1179 | else | ||
1180 | { | ||
1181 | const char *tstr = real->doc ? dgettext (state->root_argp->argp_domain, | ||
1182 | real->doc) : 0; | ||
1183 | const char *fstr = filter_doc (tstr, real->key, entry->argp, state); | ||
1184 | if (fstr && *fstr) | ||
1185 | { | ||
1186 | unsigned int col = __argp_fmtstream_point (stream); | ||
1187 | |||
1188 | __argp_fmtstream_set_lmargin (stream, uparams.opt_doc_col); | ||
1189 | __argp_fmtstream_set_wmargin (stream, uparams.opt_doc_col); | ||
1190 | |||
1191 | if (col > (unsigned int) (uparams.opt_doc_col + 3)) | ||
1192 | __argp_fmtstream_putc (stream, '\n'); | ||
1193 | else if (col >= (unsigned int) uparams.opt_doc_col) | ||
1194 | __argp_fmtstream_puts (stream, " "); | ||
1195 | else | ||
1196 | indent_to (stream, uparams.opt_doc_col); | ||
1197 | |||
1198 | __argp_fmtstream_puts (stream, fstr); | ||
1199 | } | ||
1200 | if (fstr && fstr != tstr) | ||
1201 | free ((char *) fstr); | ||
1202 | |||
1203 | /* Reset the left margin. */ | ||
1204 | __argp_fmtstream_set_lmargin (stream, 0); | ||
1205 | __argp_fmtstream_putc (stream, '\n'); | ||
1206 | } | ||
1207 | |||
1208 | hhstate->prev_entry = entry; | ||
1209 | |||
1210 | cleanup: | ||
1211 | __argp_fmtstream_set_lmargin (stream, old_lm); | ||
1212 | __argp_fmtstream_set_wmargin (stream, old_wm); | ||
1213 | } | ||
1214 | |||
1215 | /* Output a long help message about the options in HOL to STREAM. */ | ||
1216 | static void | ||
1217 | hol_help (struct hol *hol, const struct argp_state *state, | ||
1218 | argp_fmtstream_t stream) | ||
1219 | { | ||
1220 | unsigned num; | ||
1221 | struct hol_entry *entry; | ||
1222 | struct hol_help_state hhstate = { 0, 0, 0 }; | ||
1223 | |||
1224 | for (entry = hol->entries, num = hol->num_entries; num > 0; entry++, num--) | ||
1225 | hol_entry_help (entry, state, stream, &hhstate); | ||
1226 | |||
1227 | if (hhstate.suppressed_dup_arg && uparams.dup_args_note) | ||
1228 | { | ||
1229 | const char *tstr = dgettext (state->root_argp->argp_domain, "\ | ||
1230 | Mandatory or optional arguments to long options are also mandatory or \ | ||
1231 | optional for any corresponding short options."); | ||
1232 | const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_DUP_ARGS_NOTE, | ||
1233 | state ? state->root_argp : 0, state); | ||
1234 | if (fstr && *fstr) | ||
1235 | { | ||
1236 | __argp_fmtstream_putc (stream, '\n'); | ||
1237 | __argp_fmtstream_puts (stream, fstr); | ||
1238 | __argp_fmtstream_putc (stream, '\n'); | ||
1239 | } | ||
1240 | if (fstr && fstr != tstr) | ||
1241 | free ((char *) fstr); | ||
1242 | } | ||
1243 | } | ||
1244 | |||
1245 | /* Helper functions for hol_usage. */ | ||
1246 | |||
1247 | /* If OPT is a short option without an arg, append its key to the string | ||
1248 | pointer pointer to by COOKIE, and advance the pointer. */ | ||
1249 | static int | ||
1250 | add_argless_short_opt (const struct argp_option *opt, | ||
1251 | const struct argp_option *real, | ||
1252 | const char *domain, void *cookie) | ||
1253 | { | ||
1254 | char **snao_end = cookie; | ||
1255 | if (!(opt->arg || real->arg) | ||
1256 | && !((opt->flags | real->flags) & OPTION_NO_USAGE)) | ||
1257 | *(*snao_end)++ = opt->key; | ||
1258 | return 0; | ||
1259 | } | ||
1260 | |||
1261 | /* If OPT is a short option with an arg, output a usage entry for it to the | ||
1262 | stream pointed at by COOKIE. */ | ||
1263 | static int | ||
1264 | usage_argful_short_opt (const struct argp_option *opt, | ||
1265 | const struct argp_option *real, | ||
1266 | const char *domain, void *cookie) | ||
1267 | { | ||
1268 | argp_fmtstream_t stream = cookie; | ||
1269 | const char *arg = opt->arg; | ||
1270 | int flags = opt->flags | real->flags; | ||
1271 | |||
1272 | if (! arg) | ||
1273 | arg = real->arg; | ||
1274 | |||
1275 | if (arg && !(flags & OPTION_NO_USAGE)) | ||
1276 | { | ||
1277 | arg = dgettext (domain, arg); | ||
1278 | |||
1279 | if (flags & OPTION_ARG_OPTIONAL) | ||
1280 | __argp_fmtstream_printf (stream, " [-%c[%s]]", opt->key, arg); | ||
1281 | else | ||
1282 | { | ||
1283 | /* Manually do line wrapping so that it (probably) won't | ||
1284 | get wrapped at the embedded space. */ | ||
1285 | space (stream, 6 + strlen (arg)); | ||
1286 | __argp_fmtstream_printf (stream, "[-%c %s]", opt->key, arg); | ||
1287 | } | ||
1288 | } | ||
1289 | |||
1290 | return 0; | ||
1291 | } | ||
1292 | |||
1293 | /* Output a usage entry for the long option opt to the stream pointed at by | ||
1294 | COOKIE. */ | ||
1295 | static int | ||
1296 | usage_long_opt (const struct argp_option *opt, | ||
1297 | const struct argp_option *real, | ||
1298 | const char *domain, void *cookie) | ||
1299 | { | ||
1300 | argp_fmtstream_t stream = cookie; | ||
1301 | const char *arg = opt->arg; | ||
1302 | int flags = opt->flags | real->flags; | ||
1303 | |||
1304 | if (! arg) | ||
1305 | arg = real->arg; | ||
1306 | |||
1307 | if (! (flags & OPTION_NO_USAGE) && !odoc (opt)) | ||
1308 | { | ||
1309 | if (arg) | ||
1310 | { | ||
1311 | arg = dgettext (domain, arg); | ||
1312 | if (flags & OPTION_ARG_OPTIONAL) | ||
1313 | __argp_fmtstream_printf (stream, " [--%s[=%s]]", opt->name, arg); | ||
1314 | else | ||
1315 | __argp_fmtstream_printf (stream, " [--%s=%s]", opt->name, arg); | ||
1316 | } | ||
1317 | else | ||
1318 | __argp_fmtstream_printf (stream, " [--%s]", opt->name); | ||
1319 | } | ||
1320 | |||
1321 | return 0; | ||
1322 | } | ||
1323 | |||
1324 | /* Print a short usage description for the arguments in HOL to STREAM. */ | ||
1325 | static void | ||
1326 | hol_usage (struct hol *hol, argp_fmtstream_t stream) | ||
1327 | { | ||
1328 | if (hol->num_entries > 0) | ||
1329 | { | ||
1330 | unsigned nentries; | ||
1331 | struct hol_entry *entry; | ||
1332 | char *short_no_arg_opts = alloca (strlen (hol->short_options) + 1); | ||
1333 | char *snao_end = short_no_arg_opts; | ||
1334 | |||
1335 | /* First we put a list of short options without arguments. */ | ||
1336 | for (entry = hol->entries, nentries = hol->num_entries | ||
1337 | ; nentries > 0 | ||
1338 | ; entry++, nentries--) | ||
1339 | hol_entry_short_iterate (entry, add_argless_short_opt, | ||
1340 | entry->argp->argp_domain, &snao_end); | ||
1341 | if (snao_end > short_no_arg_opts) | ||
1342 | { | ||
1343 | *snao_end++ = 0; | ||
1344 | __argp_fmtstream_printf (stream, " [-%s]", short_no_arg_opts); | ||
1345 | } | ||
1346 | |||
1347 | /* Now a list of short options *with* arguments. */ | ||
1348 | for (entry = hol->entries, nentries = hol->num_entries | ||
1349 | ; nentries > 0 | ||
1350 | ; entry++, nentries--) | ||
1351 | hol_entry_short_iterate (entry, usage_argful_short_opt, | ||
1352 | entry->argp->argp_domain, stream); | ||
1353 | |||
1354 | /* Finally, a list of long options (whew!). */ | ||
1355 | for (entry = hol->entries, nentries = hol->num_entries | ||
1356 | ; nentries > 0 | ||
1357 | ; entry++, nentries--) | ||
1358 | hol_entry_long_iterate (entry, usage_long_opt, | ||
1359 | entry->argp->argp_domain, stream); | ||
1360 | } | ||
1361 | } | ||
1362 | |||
1363 | /* Make a HOL containing all levels of options in ARGP. CLUSTER is the | ||
1364 | cluster in which ARGP's entries should be clustered, or 0. */ | ||
1365 | static struct hol * | ||
1366 | argp_hol (const struct argp *argp, struct hol_cluster *cluster) | ||
1367 | { | ||
1368 | const struct argp_child *child = argp->children; | ||
1369 | struct hol *hol = make_hol (argp, cluster); | ||
1370 | if (child) | ||
1371 | while (child->argp) | ||
1372 | { | ||
1373 | struct hol_cluster *child_cluster = | ||
1374 | ((child->group || child->header) | ||
1375 | /* Put CHILD->argp within its own cluster. */ | ||
1376 | ? hol_add_cluster (hol, child->group, child->header, | ||
1377 | child - argp->children, cluster, argp) | ||
1378 | /* Just merge it into the parent's cluster. */ | ||
1379 | : cluster); | ||
1380 | hol_append (hol, argp_hol (child->argp, child_cluster)) ; | ||
1381 | child++; | ||
1382 | } | ||
1383 | return hol; | ||
1384 | } | ||
1385 | |||
1386 | /* Calculate how many different levels with alternative args strings exist in | ||
1387 | ARGP. */ | ||
1388 | static size_t | ||
1389 | argp_args_levels (const struct argp *argp) | ||
1390 | { | ||
1391 | size_t levels = 0; | ||
1392 | const struct argp_child *child = argp->children; | ||
1393 | |||
1394 | if (argp->args_doc && strchr (argp->args_doc, '\n')) | ||
1395 | levels++; | ||
1396 | |||
1397 | if (child) | ||
1398 | while (child->argp) | ||
1399 | levels += argp_args_levels ((child++)->argp); | ||
1400 | |||
1401 | return levels; | ||
1402 | } | ||
1403 | |||
1404 | /* Print all the non-option args documented in ARGP to STREAM. Any output is | ||
1405 | preceded by a space. LEVELS is a pointer to a byte vector the length | ||
1406 | returned by argp_args_levels; it should be initialized to zero, and | ||
1407 | updated by this routine for the next call if ADVANCE is true. True is | ||
1408 | returned as long as there are more patterns to output. */ | ||
1409 | static int | ||
1410 | argp_args_usage (const struct argp *argp, const struct argp_state *state, | ||
1411 | char **levels, int advance, argp_fmtstream_t stream) | ||
1412 | { | ||
1413 | char *our_level = *levels; | ||
1414 | int multiple = 0; | ||
1415 | const struct argp_child *child = argp->children; | ||
1416 | const char *tdoc = dgettext (argp->argp_domain, argp->args_doc), *nl = 0; | ||
1417 | const char *fdoc = filter_doc (tdoc, ARGP_KEY_HELP_ARGS_DOC, argp, state); | ||
1418 | |||
1419 | if (fdoc) | ||
1420 | { | ||
1421 | const char *cp = fdoc; | ||
1422 | nl = __strchrnul (cp, '\n'); | ||
1423 | if (*nl != '\0') | ||
1424 | /* This is a `multi-level' args doc; advance to the correct position | ||
1425 | as determined by our state in LEVELS, and update LEVELS. */ | ||
1426 | { | ||
1427 | int i; | ||
1428 | multiple = 1; | ||
1429 | for (i = 0; i < *our_level; i++) | ||
1430 | cp = nl + 1, nl = __strchrnul (cp, '\n'); | ||
1431 | (*levels)++; | ||
1432 | } | ||
1433 | |||
1434 | /* Manually do line wrapping so that it (probably) won't get wrapped at | ||
1435 | any embedded spaces. */ | ||
1436 | space (stream, 1 + nl - cp); | ||
1437 | |||
1438 | __argp_fmtstream_write (stream, cp, nl - cp); | ||
1439 | } | ||
1440 | if (fdoc && fdoc != tdoc) | ||
1441 | free ((char *)fdoc); /* Free user's modified doc string. */ | ||
1442 | |||
1443 | if (child) | ||
1444 | while (child->argp) | ||
1445 | advance = !argp_args_usage ((child++)->argp, state, levels, advance, stream); | ||
1446 | |||
1447 | if (advance && multiple) | ||
1448 | { | ||
1449 | /* Need to increment our level. */ | ||
1450 | if (*nl) | ||
1451 | /* There's more we can do here. */ | ||
1452 | { | ||
1453 | (*our_level)++; | ||
1454 | advance = 0; /* Our parent shouldn't advance also. */ | ||
1455 | } | ||
1456 | else if (*our_level > 0) | ||
1457 | /* We had multiple levels, but used them up; reset to zero. */ | ||
1458 | *our_level = 0; | ||
1459 | } | ||
1460 | |||
1461 | return !advance; | ||
1462 | } | ||
1463 | |||
1464 | /* Print the documentation for ARGP to STREAM; if POST is false, then | ||
1465 | everything preceeding a `\v' character in the documentation strings (or | ||
1466 | the whole string, for those with none) is printed, otherwise, everything | ||
1467 | following the `\v' character (nothing for strings without). Each separate | ||
1468 | bit of documentation is separated a blank line, and if PRE_BLANK is true, | ||
1469 | then the first is as well. If FIRST_ONLY is true, only the first | ||
1470 | occurrence is output. Returns true if anything was output. */ | ||
1471 | static int | ||
1472 | argp_doc (const struct argp *argp, const struct argp_state *state, | ||
1473 | int post, int pre_blank, int first_only, | ||
1474 | argp_fmtstream_t stream) | ||
1475 | { | ||
1476 | const char *text; | ||
1477 | const char *inp_text; | ||
1478 | size_t inp_text_len = 0; | ||
1479 | const char *trans_text; | ||
1480 | void *input = 0; | ||
1481 | int anything = 0; | ||
1482 | const struct argp_child *child = argp->children; | ||
1483 | |||
1484 | if (argp->doc) | ||
1485 | { | ||
1486 | char *vt = strchr (argp->doc, '\v'); | ||
1487 | if (vt) | ||
1488 | { | ||
1489 | if (post) | ||
1490 | inp_text = vt + 1; | ||
1491 | else | ||
1492 | { | ||
1493 | inp_text_len = vt - argp->doc; | ||
1494 | inp_text = __strndup (argp->doc, inp_text_len); | ||
1495 | } | ||
1496 | } | ||
1497 | else | ||
1498 | inp_text = post ? 0 : argp->doc; | ||
1499 | trans_text = dgettext (argp->argp_domain, inp_text); | ||
1500 | } | ||
1501 | else | ||
1502 | trans_text = inp_text = 0; | ||
1503 | |||
1504 | if (argp->help_filter) | ||
1505 | /* We have to filter the doc strings. */ | ||
1506 | { | ||
1507 | input = __argp_input (argp, state); | ||
1508 | text = | ||
1509 | (*argp->help_filter) (post | ||
1510 | ? ARGP_KEY_HELP_POST_DOC | ||
1511 | : ARGP_KEY_HELP_PRE_DOC, | ||
1512 | trans_text, input); | ||
1513 | } | ||
1514 | else | ||
1515 | text = (const char *) trans_text; | ||
1516 | |||
1517 | if (text) | ||
1518 | { | ||
1519 | if (pre_blank) | ||
1520 | __argp_fmtstream_putc (stream, '\n'); | ||
1521 | |||
1522 | __argp_fmtstream_puts (stream, text); | ||
1523 | |||
1524 | if (__argp_fmtstream_point (stream) > __argp_fmtstream_lmargin (stream)) | ||
1525 | __argp_fmtstream_putc (stream, '\n'); | ||
1526 | |||
1527 | anything = 1; | ||
1528 | } | ||
1529 | |||
1530 | if (text && text != trans_text) | ||
1531 | free ((char *) text); /* Free TEXT returned from the help filter. */ | ||
1532 | |||
1533 | if (inp_text && inp_text_len) | ||
1534 | free ((char *) inp_text); /* We copied INP_TEXT, so free it now. */ | ||
1535 | |||
1536 | if (post && argp->help_filter) | ||
1537 | /* Now see if we have to output a ARGP_KEY_HELP_EXTRA text. */ | ||
1538 | { | ||
1539 | text = (*argp->help_filter) (ARGP_KEY_HELP_EXTRA, 0, input); | ||
1540 | if (text) | ||
1541 | { | ||
1542 | if (anything || pre_blank) | ||
1543 | __argp_fmtstream_putc (stream, '\n'); | ||
1544 | __argp_fmtstream_puts (stream, text); | ||
1545 | free ((char *) text); | ||
1546 | if (__argp_fmtstream_point (stream) | ||
1547 | > __argp_fmtstream_lmargin (stream)) | ||
1548 | __argp_fmtstream_putc (stream, '\n'); | ||
1549 | anything = 1; | ||
1550 | } | ||
1551 | } | ||
1552 | |||
1553 | if (child) | ||
1554 | while (child->argp && !(first_only && anything)) | ||
1555 | anything |= | ||
1556 | argp_doc ((child++)->argp, state, | ||
1557 | post, anything || pre_blank, first_only, | ||
1558 | stream); | ||
1559 | |||
1560 | return anything; | ||
1561 | } | ||
1562 | |||
1563 | /* Output a usage message for ARGP to STREAM. If called from | ||
1564 | argp_state_help, STATE is the relevent parsing state. FLAGS are from the | ||
1565 | set ARGP_HELP_*. NAME is what to use wherever a `program name' is | ||
1566 | needed. */ | ||
1567 | static void | ||
1568 | _help (const struct argp *argp, const struct argp_state *state, FILE *stream, | ||
1569 | unsigned flags, char *name) | ||
1570 | { | ||
1571 | int anything = 0; /* Whether we've output anything. */ | ||
1572 | struct hol *hol = 0; | ||
1573 | argp_fmtstream_t fs; | ||
1574 | |||
1575 | if (! stream) | ||
1576 | return; | ||
1577 | |||
1578 | #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) | ||
1579 | __flockfile (stream); | ||
1580 | #endif | ||
1581 | |||
1582 | if (! uparams.valid) | ||
1583 | fill_in_uparams (state); | ||
1584 | |||
1585 | fs = __argp_make_fmtstream (stream, 0, uparams.rmargin, 0); | ||
1586 | if (! fs) | ||
1587 | { | ||
1588 | #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) | ||
1589 | __funlockfile (stream); | ||
1590 | #endif | ||
1591 | return; | ||
1592 | } | ||
1593 | |||
1594 | if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG)) | ||
1595 | { | ||
1596 | hol = argp_hol (argp, 0); | ||
1597 | |||
1598 | /* If present, these options always come last. */ | ||
1599 | hol_set_group (hol, "help", -1); | ||
1600 | hol_set_group (hol, "version", -1); | ||
1601 | |||
1602 | hol_sort (hol); | ||
1603 | } | ||
1604 | |||
1605 | if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE)) | ||
1606 | /* Print a short `Usage:' message. */ | ||
1607 | { | ||
1608 | int first_pattern = 1, more_patterns; | ||
1609 | size_t num_pattern_levels = argp_args_levels (argp); | ||
1610 | char *pattern_levels = alloca (num_pattern_levels); | ||
1611 | |||
1612 | memset (pattern_levels, 0, num_pattern_levels); | ||
1613 | |||
1614 | do | ||
1615 | { | ||
1616 | int old_lm; | ||
1617 | int old_wm = __argp_fmtstream_set_wmargin (fs, uparams.usage_indent); | ||
1618 | char *levels = pattern_levels; | ||
1619 | |||
1620 | if (first_pattern) | ||
1621 | __argp_fmtstream_printf (fs, "%s %s", | ||
1622 | dgettext (argp->argp_domain, "Usage:"), | ||
1623 | name); | ||
1624 | else | ||
1625 | __argp_fmtstream_printf (fs, "%s %s", | ||
1626 | dgettext (argp->argp_domain, " or: "), | ||
1627 | name); | ||
1628 | |||
1629 | /* We set the lmargin as well as the wmargin, because hol_usage | ||
1630 | manually wraps options with newline to avoid annoying breaks. */ | ||
1631 | old_lm = __argp_fmtstream_set_lmargin (fs, uparams.usage_indent); | ||
1632 | |||
1633 | if (flags & ARGP_HELP_SHORT_USAGE) | ||
1634 | /* Just show where the options go. */ | ||
1635 | { | ||
1636 | if (hol->num_entries > 0) | ||
1637 | __argp_fmtstream_puts (fs, dgettext (argp->argp_domain, | ||
1638 | " [OPTION...]")); | ||
1639 | } | ||
1640 | else | ||
1641 | /* Actually print the options. */ | ||
1642 | { | ||
1643 | hol_usage (hol, fs); | ||
1644 | flags |= ARGP_HELP_SHORT_USAGE; /* But only do so once. */ | ||
1645 | } | ||
1646 | |||
1647 | more_patterns = argp_args_usage (argp, state, &levels, 1, fs); | ||
1648 | |||
1649 | __argp_fmtstream_set_wmargin (fs, old_wm); | ||
1650 | __argp_fmtstream_set_lmargin (fs, old_lm); | ||
1651 | |||
1652 | __argp_fmtstream_putc (fs, '\n'); | ||
1653 | anything = 1; | ||
1654 | |||
1655 | first_pattern = 0; | ||
1656 | } | ||
1657 | while (more_patterns); | ||
1658 | } | ||
1659 | |||
1660 | if (flags & ARGP_HELP_PRE_DOC) | ||
1661 | anything |= argp_doc (argp, state, 0, 0, 1, fs); | ||
1662 | |||
1663 | if (flags & ARGP_HELP_SEE) | ||
1664 | { | ||
1665 | __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, "\ | ||
1666 | Try `%s --help' or `%s --usage' for more information.\n"), | ||
1667 | name, name); | ||
1668 | anything = 1; | ||
1669 | } | ||
1670 | |||
1671 | if (flags & ARGP_HELP_LONG) | ||
1672 | /* Print a long, detailed help message. */ | ||
1673 | { | ||
1674 | /* Print info about all the options. */ | ||
1675 | if (hol->num_entries > 0) | ||
1676 | { | ||
1677 | if (anything) | ||
1678 | __argp_fmtstream_putc (fs, '\n'); | ||
1679 | hol_help (hol, state, fs); | ||
1680 | anything = 1; | ||
1681 | } | ||
1682 | } | ||
1683 | |||
1684 | if (flags & ARGP_HELP_POST_DOC) | ||
1685 | /* Print any documentation strings at the end. */ | ||
1686 | anything |= argp_doc (argp, state, 1, anything, 0, fs); | ||
1687 | |||
1688 | if ((flags & ARGP_HELP_BUG_ADDR) && argp_program_bug_address) | ||
1689 | { | ||
1690 | if (anything) | ||
1691 | __argp_fmtstream_putc (fs, '\n'); | ||
1692 | __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, | ||
1693 | "Report bugs to %s.\n"), | ||
1694 | argp_program_bug_address); | ||
1695 | anything = 1; | ||
1696 | } | ||
1697 | |||
1698 | #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) | ||
1699 | __funlockfile (stream); | ||
1700 | #endif | ||
1701 | |||
1702 | if (hol) | ||
1703 | hol_free (hol); | ||
1704 | |||
1705 | __argp_fmtstream_free (fs); | ||
1706 | } | ||
1707 | |||
1708 | /* Output a usage message for ARGP to STREAM. FLAGS are from the set | ||
1709 | ARGP_HELP_*. NAME is what to use wherever a `program name' is needed. */ | ||
1710 | void __argp_help (const struct argp *argp, FILE *stream, | ||
1711 | unsigned flags, char *name) | ||
1712 | { | ||
1713 | struct argp_state state; | ||
1714 | memset (&state, 0, sizeof state); | ||
1715 | state.root_argp = argp; | ||
1716 | _help (argp, &state, stream, flags, name); | ||
1717 | } | ||
1718 | #ifdef weak_alias | ||
1719 | weak_alias (__argp_help, argp_help) | ||
1720 | #endif | ||
1721 | |||
1722 | #if ! (defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME) | ||
1723 | char * | ||
1724 | __argp_short_program_name (void) | ||
1725 | { | ||
1726 | # if HAVE_DECL_PROGRAM_INVOCATION_NAME | ||
1727 | return __argp_base_name (program_invocation_name); | ||
1728 | # else | ||
1729 | /* FIXME: What now? Miles suggests that it is better to use NULL, | ||
1730 | but currently the value is passed on directly to fputs_unlocked, | ||
1731 | so that requires more changes. */ | ||
1732 | # if __GNUC__ | ||
1733 | # warning No reasonable value to return | ||
1734 | # endif /* __GNUC__ */ | ||
1735 | return ""; | ||
1736 | # endif | ||
1737 | } | ||
1738 | #endif | ||
1739 | |||
1740 | /* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are | ||
1741 | from the set ARGP_HELP_*. */ | ||
1742 | void | ||
1743 | __argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags) | ||
1744 | { | ||
1745 | if ((!state || ! (state->flags & ARGP_NO_ERRS)) && stream) | ||
1746 | { | ||
1747 | if (state && (state->flags & ARGP_LONG_ONLY)) | ||
1748 | flags |= ARGP_HELP_LONG_ONLY; | ||
1749 | |||
1750 | _help (state ? state->root_argp : 0, state, stream, flags, | ||
1751 | state ? state->name : __argp_short_program_name ()); | ||
1752 | |||
1753 | if (!state || ! (state->flags & ARGP_NO_EXIT)) | ||
1754 | { | ||
1755 | if (flags & ARGP_HELP_EXIT_ERR) | ||
1756 | exit (argp_err_exit_status); | ||
1757 | if (flags & ARGP_HELP_EXIT_OK) | ||
1758 | exit (0); | ||
1759 | } | ||
1760 | } | ||
1761 | } | ||
1762 | #ifdef weak_alias | ||
1763 | weak_alias (__argp_state_help, argp_state_help) | ||
1764 | #endif | ||
1765 | |||
1766 | /* If appropriate, print the printf string FMT and following args, preceded | ||
1767 | by the program name and `:', to stderr, and followed by a `Try ... --help' | ||
1768 | message, then exit (1). */ | ||
1769 | void | ||
1770 | __argp_error (const struct argp_state *state, const char *fmt, ...) | ||
1771 | { | ||
1772 | if (!state || !(state->flags & ARGP_NO_ERRS)) | ||
1773 | { | ||
1774 | FILE *stream = state ? state->err_stream : stderr; | ||
1775 | |||
1776 | if (stream) | ||
1777 | { | ||
1778 | va_list ap; | ||
1779 | |||
1780 | #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) | ||
1781 | __flockfile (stream); | ||
1782 | #endif | ||
1783 | |||
1784 | va_start (ap, fmt); | ||
1785 | |||
1786 | #ifdef USE_IN_LIBIO | ||
1787 | if (_IO_fwide (stream, 0) > 0) | ||
1788 | { | ||
1789 | char *buf; | ||
1790 | |||
1791 | if (__asprintf (&buf, fmt, ap) < 0) | ||
1792 | buf = NULL; | ||
1793 | |||
1794 | __fwprintf (stream, L"%s: %s\n", | ||
1795 | state ? state->name : __argp_short_program_name (), | ||
1796 | buf); | ||
1797 | |||
1798 | free (buf); | ||
1799 | } | ||
1800 | else | ||
1801 | #endif | ||
1802 | { | ||
1803 | fputs_unlocked (state | ||
1804 | ? state->name : __argp_short_program_name (), | ||
1805 | stream); | ||
1806 | putc_unlocked (':', stream); | ||
1807 | putc_unlocked (' ', stream); | ||
1808 | |||
1809 | vfprintf (stream, fmt, ap); | ||
1810 | |||
1811 | putc_unlocked ('\n', stream); | ||
1812 | } | ||
1813 | |||
1814 | __argp_state_help (state, stream, ARGP_HELP_STD_ERR); | ||
1815 | |||
1816 | va_end (ap); | ||
1817 | |||
1818 | #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) | ||
1819 | __funlockfile (stream); | ||
1820 | #endif | ||
1821 | } | ||
1822 | } | ||
1823 | } | ||
1824 | #ifdef weak_alias | ||
1825 | weak_alias (__argp_error, argp_error) | ||
1826 | #endif | ||
1827 | |||
1828 | /* Similar to the standard gnu error-reporting function error(), but will | ||
1829 | respect the ARGP_NO_EXIT and ARGP_NO_ERRS flags in STATE, and will print | ||
1830 | to STATE->err_stream. This is useful for argument parsing code that is | ||
1831 | shared between program startup (when exiting is desired) and runtime | ||
1832 | option parsing (when typically an error code is returned instead). The | ||
1833 | difference between this function and argp_error is that the latter is for | ||
1834 | *parsing errors*, and the former is for other problems that occur during | ||
1835 | parsing but don't reflect a (syntactic) problem with the input. */ | ||
1836 | void | ||
1837 | __argp_failure (const struct argp_state *state, int status, int errnum, | ||
1838 | const char *fmt, ...) | ||
1839 | { | ||
1840 | if (!state || !(state->flags & ARGP_NO_ERRS)) | ||
1841 | { | ||
1842 | FILE *stream = state ? state->err_stream : stderr; | ||
1843 | |||
1844 | if (stream) | ||
1845 | { | ||
1846 | #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) | ||
1847 | __flockfile (stream); | ||
1848 | #endif | ||
1849 | |||
1850 | #ifdef USE_IN_LIBIO | ||
1851 | if (_IO_fwide (stream, 0) > 0) | ||
1852 | __fwprintf (stream, L"%s", | ||
1853 | state ? state->name : __argp_short_program_name ()); | ||
1854 | else | ||
1855 | #endif | ||
1856 | fputs_unlocked (state | ||
1857 | ? state->name : __argp_short_program_name (), | ||
1858 | stream); | ||
1859 | |||
1860 | if (fmt) | ||
1861 | { | ||
1862 | va_list ap; | ||
1863 | |||
1864 | va_start (ap, fmt); | ||
1865 | #ifdef USE_IN_LIBIO | ||
1866 | if (_IO_fwide (stream, 0) > 0) | ||
1867 | { | ||
1868 | char *buf; | ||
1869 | |||
1870 | if (__asprintf (&buf, fmt, ap) < 0) | ||
1871 | buf = NULL; | ||
1872 | |||
1873 | __fwprintf (stream, L": %s", buf); | ||
1874 | |||
1875 | free (buf); | ||
1876 | } | ||
1877 | else | ||
1878 | #endif | ||
1879 | { | ||
1880 | putc_unlocked (':', stream); | ||
1881 | putc_unlocked (' ', stream); | ||
1882 | |||
1883 | vfprintf (stream, fmt, ap); | ||
1884 | } | ||
1885 | |||
1886 | va_end (ap); | ||
1887 | } | ||
1888 | |||
1889 | if (errnum) | ||
1890 | { | ||
1891 | char buf[200]; | ||
1892 | |||
1893 | #ifdef USE_IN_LIBIO | ||
1894 | if (_IO_fwide (stream, 0) > 0) | ||
1895 | __fwprintf (stream, L": %s", | ||
1896 | __strerror_r (errnum, buf, sizeof (buf))); | ||
1897 | else | ||
1898 | #endif | ||
1899 | { | ||
1900 | char const *s = NULL; | ||
1901 | putc_unlocked (':', stream); | ||
1902 | putc_unlocked (' ', stream); | ||
1903 | #if _LIBC || (HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P) | ||
1904 | s = __strerror_r (errnum, buf, sizeof buf); | ||
1905 | #elif HAVE_DECL_STRERROR_R | ||
1906 | if (__strerror_r (errnum, buf, sizeof buf) == 0) | ||
1907 | s = buf; | ||
1908 | #endif | ||
1909 | #if !_LIBC | ||
1910 | if (! s && ! (s = strerror (errnum))) | ||
1911 | s = dgettext (state->root_argp->argp_domain, | ||
1912 | "Unknown system error"); | ||
1913 | #endif | ||
1914 | fputs (s, stream); | ||
1915 | } | ||
1916 | } | ||
1917 | |||
1918 | #ifdef USE_IN_LIBIO | ||
1919 | if (_IO_fwide (stream, 0) > 0) | ||
1920 | putwc_unlocked (L'\n', stream); | ||
1921 | else | ||
1922 | #endif | ||
1923 | putc_unlocked ('\n', stream); | ||
1924 | |||
1925 | #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) | ||
1926 | __funlockfile (stream); | ||
1927 | #endif | ||
1928 | |||
1929 | if (status && (!state || !(state->flags & ARGP_NO_EXIT))) | ||
1930 | exit (status); | ||
1931 | } | ||
1932 | } | ||
1933 | } | ||
1934 | #ifdef weak_alias | ||
1935 | weak_alias (__argp_failure, argp_failure) | ||
1936 | #endif |
mailbox/argp-namefrob.h
deleted
100644 → 0
1 | /* Name frobnication for compiling argp outside of glibc | ||
2 | Copyright (C) 1997, 2003 Free Software Foundation, Inc. | ||
3 | This file is part of the GNU C Library. | ||
4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. | ||
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 | #if !_LIBC | ||
21 | /* This code is written for inclusion in gnu-libc, and uses names in the | ||
22 | namespace reserved for libc. If we're not compiling in libc, define those | ||
23 | names to be the normal ones instead. */ | ||
24 | |||
25 | /* argp-parse functions */ | ||
26 | #undef __argp_parse | ||
27 | #define __argp_parse argp_parse | ||
28 | #undef __option_is_end | ||
29 | #define __option_is_end _option_is_end | ||
30 | #undef __option_is_short | ||
31 | #define __option_is_short _option_is_short | ||
32 | #undef __argp_input | ||
33 | #define __argp_input _argp_input | ||
34 | |||
35 | /* argp-help functions */ | ||
36 | #undef __argp_help | ||
37 | #define __argp_help argp_help | ||
38 | #undef __argp_error | ||
39 | #define __argp_error argp_error | ||
40 | #undef __argp_failure | ||
41 | #define __argp_failure argp_failure | ||
42 | #undef __argp_state_help | ||
43 | #define __argp_state_help argp_state_help | ||
44 | #undef __argp_usage | ||
45 | #define __argp_usage argp_usage | ||
46 | |||
47 | /* argp-fmtstream functions */ | ||
48 | #undef __argp_make_fmtstream | ||
49 | #define __argp_make_fmtstream argp_make_fmtstream | ||
50 | #undef __argp_fmtstream_free | ||
51 | #define __argp_fmtstream_free argp_fmtstream_free | ||
52 | #undef __argp_fmtstream_putc | ||
53 | #define __argp_fmtstream_putc argp_fmtstream_putc | ||
54 | #undef __argp_fmtstream_puts | ||
55 | #define __argp_fmtstream_puts argp_fmtstream_puts | ||
56 | #undef __argp_fmtstream_write | ||
57 | #define __argp_fmtstream_write argp_fmtstream_write | ||
58 | #undef __argp_fmtstream_printf | ||
59 | #define __argp_fmtstream_printf argp_fmtstream_printf | ||
60 | #undef __argp_fmtstream_set_lmargin | ||
61 | #define __argp_fmtstream_set_lmargin argp_fmtstream_set_lmargin | ||
62 | #undef __argp_fmtstream_set_rmargin | ||
63 | #define __argp_fmtstream_set_rmargin argp_fmtstream_set_rmargin | ||
64 | #undef __argp_fmtstream_set_wmargin | ||
65 | #define __argp_fmtstream_set_wmargin argp_fmtstream_set_wmargin | ||
66 | #undef __argp_fmtstream_point | ||
67 | #define __argp_fmtstream_point argp_fmtstream_point | ||
68 | #undef __argp_fmtstream_update | ||
69 | #define __argp_fmtstream_update _argp_fmtstream_update | ||
70 | #undef __argp_fmtstream_ensure | ||
71 | #define __argp_fmtstream_ensure _argp_fmtstream_ensure | ||
72 | #undef __argp_fmtstream_lmargin | ||
73 | #define __argp_fmtstream_lmargin argp_fmtstream_lmargin | ||
74 | #undef __argp_fmtstream_rmargin | ||
75 | #define __argp_fmtstream_rmargin argp_fmtstream_rmargin | ||
76 | #undef __argp_fmtstream_wmargin | ||
77 | #define __argp_fmtstream_wmargin argp_fmtstream_wmargin | ||
78 | |||
79 | #include "mempcpy.h" | ||
80 | #include "strcase.h" | ||
81 | #include "strchrnul.h" | ||
82 | #include "strndup.h" | ||
83 | |||
84 | /* normal libc functions we call */ | ||
85 | #undef __flockfile | ||
86 | #define __flockfile flockfile | ||
87 | #undef __funlockfile | ||
88 | #define __funlockfile funlockfile | ||
89 | #undef __mempcpy | ||
90 | #define __mempcpy mempcpy | ||
91 | #undef __sleep | ||
92 | #define __sleep sleep | ||
93 | #undef __strcasecmp | ||
94 | #define __strcasecmp strcasecmp | ||
95 | #undef __strchrnul | ||
96 | #define __strchrnul strchrnul | ||
97 | #undef __strerror_r | ||
98 | #define __strerror_r strerror_r | ||
99 | #undef __strndup | ||
100 | #define __strndup strndup | ||
101 | #undef __vsnprintf | ||
102 | #define __vsnprintf vsnprintf | ||
103 | |||
104 | #if defined(HAVE_DECL_CLEARERR_UNLOCKED) && !HAVE_DECL_CLEARERR_UNLOCKED | ||
105 | # define clearerr_unlocked(x) clearerr (x) | ||
106 | #endif | ||
107 | #if defined(HAVE_DECL_FEOF_UNLOCKED) && !HAVE_DECL_FEOF_UNLOCKED | ||
108 | # define feof_unlocked(x) feof (x) | ||
109 | # endif | ||
110 | #if defined(HAVE_DECL_FERROR_UNLOCKED) && !HAVE_DECL_FERROR_UNLOCKED | ||
111 | # define ferror_unlocked(x) ferror (x) | ||
112 | # endif | ||
113 | #if defined(HAVE_DECL_FFLUSH_UNLOCKED) && !HAVE_DECL_FFLUSH_UNLOCKED | ||
114 | # define fflush_unlocked(x) fflush (x) | ||
115 | # endif | ||
116 | #if defined(HAVE_DECL_FGETS_UNLOCKED) && !HAVE_DECL_FGETS_UNLOCKED | ||
117 | # define fgets_unlocked(x,y,z) fgets (x,y,z) | ||
118 | # endif | ||
119 | #if defined(HAVE_DECL_FPUTC_UNLOCKED) && !HAVE_DECL_FPUTC_UNLOCKED | ||
120 | # define fputc_unlocked(x,y) fputc (x,y) | ||
121 | # endif | ||
122 | #if defined(HAVE_DECL_FPUTS_UNLOCKED) && !HAVE_DECL_FPUTS_UNLOCKED | ||
123 | # define fputs_unlocked(x,y) fputs (x,y) | ||
124 | # endif | ||
125 | #if defined(HAVE_DECL_FREAD_UNLOCKED) && !HAVE_DECL_FREAD_UNLOCKED | ||
126 | # define fread_unlocked(w,x,y,z) fread (w,x,y,z) | ||
127 | # endif | ||
128 | #if defined(HAVE_DECL_FWRITE_UNLOCKED) && !HAVE_DECL_FWRITE_UNLOCKED | ||
129 | # define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z) | ||
130 | # endif | ||
131 | #if defined(HAVE_DECL_GETC_UNLOCKED) && !HAVE_DECL_GETC_UNLOCKED | ||
132 | # define getc_unlocked(x) getc (x) | ||
133 | # endif | ||
134 | #if defined(HAVE_DECL_GETCHAR_UNLOCKED) && !HAVE_DECL_GETCHAR_UNLOCKED | ||
135 | # define getchar_unlocked() getchar () | ||
136 | # endif | ||
137 | #if defined(HAVE_DECL_PUTC_UNLOCKED) && !HAVE_DECL_PUTC_UNLOCKED | ||
138 | # define putc_unlocked(x,y) putc (x,y) | ||
139 | # endif | ||
140 | #if defined(HAVE_DECL_PUTCHAR_UNLOCKED) && !HAVE_DECL_PUTCHAR_UNLOCKED | ||
141 | # define putchar_unlocked(x) putchar (x) | ||
142 | # endif | ||
143 | |||
144 | #endif /* !_LIBC */ | ||
145 | |||
146 | #ifndef __set_errno | ||
147 | #define __set_errno(e) (errno = (e)) | ||
148 | #endif | ||
149 | |||
150 | #if defined GNULIB_ARGP_DISABLE_DIRNAME | ||
151 | # define __argp_base_name(arg) arg | ||
152 | #elif defined GNULIB_ARGP_EXTERN_BASENAME | ||
153 | extern char *__argp_base_name(const char *arg); | ||
154 | #else | ||
155 | # include "dirname.h" | ||
156 | # define __argp_base_name base_name | ||
157 | #endif | ||
158 | |||
159 | #if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME | ||
160 | # define __argp_short_program_name() (program_invocation_short_name) | ||
161 | #else | ||
162 | extern char *__argp_short_program_name (void); | ||
163 | #endif |
mailbox/argp-parse.c
deleted
100644 → 0
1 | /* Hierarchial argument parsing, layered over getopt | ||
2 | Copyright (C) 1995-2000, 2002, 2003, 2004 Free Software Foundation, Inc. | ||
3 | This file is part of the GNU C Library. | ||
4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. | ||
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 HAVE_CONFIG_H | ||
21 | # include <config.h> | ||
22 | #endif | ||
23 | |||
24 | #include <alloca.h> | ||
25 | #include <stddef.h> | ||
26 | #include <stdlib.h> | ||
27 | #include <string.h> | ||
28 | #include <unistd.h> | ||
29 | #include <limits.h> | ||
30 | #include <getopt.h> | ||
31 | #include <getopt_int.h> | ||
32 | |||
33 | #ifdef _LIBC | ||
34 | # include <libintl.h> | ||
35 | # undef dgettext | ||
36 | # define dgettext(domain, msgid) \ | ||
37 | INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES) | ||
38 | #else | ||
39 | # include "gettext.h" | ||
40 | #endif | ||
41 | #define N_(msgid) msgid | ||
42 | |||
43 | #include "argp.h" | ||
44 | #include "argp-namefrob.h" | ||
45 | |||
46 | #define alignof(type) offsetof (struct { char c; type x; }, x) | ||
47 | #define alignto(n, d) ((((n) + (d) - 1) / (d)) * (d)) | ||
48 | |||
49 | /* Getopt return values. */ | ||
50 | #define KEY_END (-1) /* The end of the options. */ | ||
51 | #define KEY_ARG 1 /* A non-option argument. */ | ||
52 | #define KEY_ERR '?' /* An error parsing the options. */ | ||
53 | |||
54 | /* The meta-argument used to prevent any further arguments being interpreted | ||
55 | as options. */ | ||
56 | #define QUOTE "--" | ||
57 | |||
58 | /* The number of bits we steal in a long-option value for our own use. */ | ||
59 | #define GROUP_BITS CHAR_BIT | ||
60 | |||
61 | /* The number of bits available for the user value. */ | ||
62 | #define USER_BITS ((sizeof ((struct option *)0)->val * CHAR_BIT) - GROUP_BITS) | ||
63 | #define USER_MASK ((1 << USER_BITS) - 1) | ||
64 | |||
65 | /* EZ alias for ARGP_ERR_UNKNOWN. */ | ||
66 | #define EBADKEY ARGP_ERR_UNKNOWN | ||
67 | |||
68 | /* Default options. */ | ||
69 | |||
70 | /* When argp is given the --HANG switch, _ARGP_HANG is set and argp will sleep | ||
71 | for one second intervals, decrementing _ARGP_HANG until it's zero. Thus | ||
72 | you can force the program to continue by attaching a debugger and setting | ||
73 | it to 0 yourself. */ | ||
74 | static volatile int _argp_hang; | ||
75 | |||
76 | #define OPT_PROGNAME -2 | ||
77 | #define OPT_USAGE -3 | ||
78 | #define OPT_HANG -4 | ||
79 | |||
80 | static const struct argp_option argp_default_options[] = | ||
81 | { | ||
82 | {"help", '?', 0, 0, N_("give this help list"), -1}, | ||
83 | {"usage", OPT_USAGE, 0, 0, N_("give a short usage message"), 0}, | ||
84 | {"program-name",OPT_PROGNAME,N_("NAME"), OPTION_HIDDEN, N_("set the program name"), 0}, | ||
85 | {"HANG", OPT_HANG, N_("SECS"), OPTION_ARG_OPTIONAL | OPTION_HIDDEN, | ||
86 | N_("hang for SECS seconds (default 3600)"), 0}, | ||
87 | {NULL, 0, 0, 0, NULL, 0} | ||
88 | }; | ||
89 | |||
90 | static error_t | ||
91 | argp_default_parser (int key, char *arg, struct argp_state *state) | ||
92 | { | ||
93 | switch (key) | ||
94 | { | ||
95 | case '?': | ||
96 | __argp_state_help (state, state->out_stream, ARGP_HELP_STD_HELP); | ||
97 | break; | ||
98 | case OPT_USAGE: | ||
99 | __argp_state_help (state, state->out_stream, | ||
100 | ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK); | ||
101 | break; | ||
102 | |||
103 | case OPT_PROGNAME: /* Set the program name. */ | ||
104 | #if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_NAME | ||
105 | program_invocation_name = arg; | ||
106 | #endif | ||
107 | /* [Note that some systems only have PROGRAM_INVOCATION_SHORT_NAME (aka | ||
108 | __PROGNAME), in which case, PROGRAM_INVOCATION_NAME is just defined | ||
109 | to be that, so we have to be a bit careful here.] */ | ||
110 | |||
111 | /* Update what we use for messages. */ | ||
112 | state->name = __argp_base_name (arg); | ||
113 | |||
114 | #if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME | ||
115 | program_invocation_short_name = state->name; | ||
116 | #endif | ||
117 | |||
118 | if ((state->flags & (ARGP_PARSE_ARGV0 | ARGP_NO_ERRS)) | ||
119 | == ARGP_PARSE_ARGV0) | ||
120 | /* Update what getopt uses too. */ | ||
121 | state->argv[0] = arg; | ||
122 | |||
123 | break; | ||
124 | |||
125 | case OPT_HANG: | ||
126 | _argp_hang = atoi (arg ? arg : "3600"); | ||
127 | while (_argp_hang-- > 0) | ||
128 | __sleep (1); | ||
129 | break; | ||
130 | |||
131 | default: | ||
132 | return EBADKEY; | ||
133 | } | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static const struct argp argp_default_argp = | ||
138 | {argp_default_options, &argp_default_parser, NULL, NULL, NULL, NULL, "libc"}; | ||
139 | |||
140 | |||
141 | static const struct argp_option argp_version_options[] = | ||
142 | { | ||
143 | {"version", 'V', 0, 0, N_("print program version"), -1}, | ||
144 | {NULL, 0, 0, 0, NULL, 0} | ||
145 | }; | ||
146 | |||
147 | static error_t | ||
148 | argp_version_parser (int key, char *arg, struct argp_state *state) | ||
149 | { | ||
150 | switch (key) | ||
151 | { | ||
152 | case 'V': | ||
153 | if (argp_program_version_hook) | ||
154 | (*argp_program_version_hook) (state->out_stream, state); | ||
155 | else if (argp_program_version) | ||
156 | fprintf (state->out_stream, "%s\n", argp_program_version); | ||
157 | else | ||
158 | __argp_error (state, dgettext (state->root_argp->argp_domain, | ||
159 | "(PROGRAM ERROR) No version known!?")); | ||
160 | if (! (state->flags & ARGP_NO_EXIT)) | ||
161 | exit (0); | ||
162 | break; | ||
163 | default: | ||
164 | return EBADKEY; | ||
165 | } | ||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | static const struct argp argp_version_argp = | ||
170 | {argp_version_options, &argp_version_parser, NULL, NULL, NULL, NULL, "libc"}; | ||
171 | |||
172 | /* Returns the offset into the getopt long options array LONG_OPTIONS of a | ||
173 | long option with called NAME, or -1 if none is found. Passing NULL as | ||
174 | NAME will return the number of options. */ | ||
175 | static int | ||
176 | find_long_option (struct option *long_options, const char *name) | ||
177 | { | ||
178 | struct option *l = long_options; | ||
179 | while (l->name != NULL) | ||
180 | if (name != NULL && strcmp (l->name, name) == 0) | ||
181 | return l - long_options; | ||
182 | else | ||
183 | l++; | ||
184 | if (name == NULL) | ||
185 | return l - long_options; | ||
186 | else | ||
187 | return -1; | ||
188 | } | ||
189 | |||
190 | |||
191 | /* The state of a `group' during parsing. Each group corresponds to a | ||
192 | particular argp structure from the tree of such descending from the top | ||
193 | level argp passed to argp_parse. */ | ||
194 | struct group | ||
195 | { | ||
196 | /* This group's parsing function. */ | ||
197 | argp_parser_t parser; | ||
198 | |||
199 | /* Which argp this group is from. */ | ||
200 | const struct argp *argp; | ||
201 | |||
202 | /* Points to the point in SHORT_OPTS corresponding to the end of the short | ||
203 | options for this group. We use it to determine from which group a | ||
204 | particular short options is from. */ | ||
205 | char *short_end; | ||
206 | |||
207 | /* The number of non-option args sucessfully handled by this parser. */ | ||
208 | unsigned args_processed; | ||
209 | |||
210 | /* This group's parser's parent's group. */ | ||
211 | struct group *parent; | ||
212 | unsigned parent_index; /* And the our position in the parent. */ | ||
213 | |||
214 | /* These fields are swapped into and out of the state structure when | ||
215 | calling this group's parser. */ | ||
216 | void *input, **child_inputs; | ||
217 | void *hook; | ||
218 | }; | ||
219 | |||
220 | /* Call GROUP's parser with KEY and ARG, swapping any group-specific info | ||
221 | from STATE before calling, and back into state afterwards. If GROUP has | ||
222 | no parser, EBADKEY is returned. */ | ||
223 | static error_t | ||
224 | group_parse (struct group *group, struct argp_state *state, int key, char *arg) | ||
225 | { | ||
226 | if (group->parser) | ||
227 | { | ||
228 | error_t err; | ||
229 | state->hook = group->hook; | ||
230 | state->input = group->input; | ||
231 | state->child_inputs = group->child_inputs; | ||
232 | state->arg_num = group->args_processed; | ||
233 | err = (*group->parser)(key, arg, state); | ||
234 | group->hook = state->hook; | ||
235 | return err; | ||
236 | } | ||
237 | else | ||
238 | return EBADKEY; | ||
239 | } | ||
240 | |||
241 | struct parser | ||
242 | { | ||
243 | const struct argp *argp; | ||
244 | |||
245 | /* SHORT_OPTS is the getopt short options string for the union of all the | ||
246 | groups of options. */ | ||
247 | char *short_opts; | ||
248 | /* LONG_OPTS is the array of getop long option structures for the union of | ||
249 | all the groups of options. */ | ||
250 | struct option *long_opts; | ||
251 | /* OPT_DATA is the getopt data used for the re-entrant getopt. */ | ||
252 | struct _getopt_data opt_data; | ||
253 | |||
254 | /* States of the various parsing groups. */ | ||
255 | struct group *groups; | ||
256 | /* The end of the GROUPS array. */ | ||
257 | struct group *egroup; | ||
258 | /* An vector containing storage for the CHILD_INPUTS field in all groups. */ | ||
259 | void **child_inputs; | ||
260 | |||
261 | /* True if we think using getopt is still useful; if false, then | ||
262 | remaining arguments are just passed verbatim with ARGP_KEY_ARG. This is | ||
263 | cleared whenever getopt returns KEY_END, but may be set again if the user | ||
264 | moves the next argument pointer backwards. */ | ||
265 | int try_getopt; | ||
266 | |||
267 | /* State block supplied to parsing routines. */ | ||
268 | struct argp_state state; | ||
269 | |||
270 | /* Memory used by this parser. */ | ||
271 | void *storage; | ||
272 | }; | ||
273 | |||
274 | /* The next usable entries in the various parser tables being filled in by | ||
275 | convert_options. */ | ||
276 | struct parser_convert_state | ||
277 | { | ||
278 | struct parser *parser; | ||
279 | char *short_end; | ||
280 | struct option *long_end; | ||
281 | void **child_inputs_end; | ||
282 | }; | ||
283 | |||
284 | /* Converts all options in ARGP (which is put in GROUP) and ancestors | ||
285 | into getopt options stored in SHORT_OPTS and LONG_OPTS; SHORT_END and | ||
286 | CVT->LONG_END are the points at which new options are added. Returns the | ||
287 | next unused group entry. CVT holds state used during the conversion. */ | ||
288 | static struct group * | ||
289 | convert_options (const struct argp *argp, | ||
290 | struct group *parent, unsigned parent_index, | ||
291 | struct group *group, struct parser_convert_state *cvt) | ||
292 | { | ||
293 | /* REAL is the most recent non-alias value of OPT. */ | ||
294 | const struct argp_option *real = argp->options; | ||
295 | const struct argp_child *children = argp->children; | ||
296 | |||
297 | if (real || argp->parser) | ||
298 | { | ||
299 | const struct argp_option *opt; | ||
300 | |||
301 | if (real) | ||
302 | for (opt = real; !__option_is_end (opt); opt++) | ||
303 | { | ||
304 | if (! (opt->flags & OPTION_ALIAS)) | ||
305 | /* OPT isn't an alias, so we can use values from it. */ | ||
306 | real = opt; | ||
307 | |||
308 | if (! (real->flags & OPTION_DOC)) | ||
309 | /* A real option (not just documentation). */ | ||
310 | { | ||
311 | if (__option_is_short (opt)) | ||
312 | /* OPT can be used as a short option. */ | ||
313 | { | ||
314 | *cvt->short_end++ = opt->key; | ||
315 | if (real->arg) | ||
316 | { | ||
317 | *cvt->short_end++ = ':'; | ||
318 | if (real->flags & OPTION_ARG_OPTIONAL) | ||
319 | *cvt->short_end++ = ':'; | ||
320 | } | ||
321 | *cvt->short_end = '\0'; /* keep 0 terminated */ | ||
322 | } | ||
323 | |||
324 | if (opt->name | ||
325 | && find_long_option (cvt->parser->long_opts, opt->name) < 0) | ||
326 | /* OPT can be used as a long option. */ | ||
327 | { | ||
328 | cvt->long_end->name = opt->name; | ||
329 | cvt->long_end->has_arg = | ||
330 | (real->arg | ||
331 | ? (real->flags & OPTION_ARG_OPTIONAL | ||
332 | ? optional_argument | ||
333 | : required_argument) | ||
334 | : no_argument); | ||
335 | cvt->long_end->flag = 0; | ||
336 | /* we add a disambiguating code to all the user's | ||
337 | values (which is removed before we actually call | ||
338 | the function to parse the value); this means that | ||
339 | the user loses use of the high 8 bits in all his | ||
340 | values (the sign of the lower bits is preserved | ||
341 | however)... */ | ||
342 | cvt->long_end->val = | ||
343 | ((opt->key | real->key) & USER_MASK) | ||
344 | + (((group - cvt->parser->groups) + 1) << USER_BITS); | ||
345 | |||
346 | /* Keep the LONG_OPTS list terminated. */ | ||
347 | (++cvt->long_end)->name = NULL; | ||
348 | } | ||
349 | } | ||
350 | } | ||
351 | |||
352 | group->parser = argp->parser; | ||
353 | group->argp = argp; | ||
354 | group->short_end = cvt->short_end; | ||
355 | group->args_processed = 0; | ||
356 | group->parent = parent; | ||
357 | group->parent_index = parent_index; | ||
358 | group->input = 0; | ||
359 | group->hook = 0; | ||
360 | group->child_inputs = 0; | ||
361 | |||
362 | if (children) | ||
363 | /* Assign GROUP's CHILD_INPUTS field some space from | ||
364 | CVT->child_inputs_end.*/ | ||
365 | { | ||
366 | unsigned num_children = 0; | ||
367 | while (children[num_children].argp) | ||
368 | num_children++; | ||
369 | group->child_inputs = cvt->child_inputs_end; | ||
370 | cvt->child_inputs_end += num_children; | ||
371 | } | ||
372 | |||
373 | parent = group++; | ||
374 | } | ||
375 | else | ||
376 | parent = 0; | ||
377 | |||
378 | if (children) | ||
379 | { | ||
380 | unsigned index = 0; | ||
381 | while (children->argp) | ||
382 | group = | ||
383 | convert_options (children++->argp, parent, index++, group, cvt); | ||
384 | } | ||
385 | |||
386 | return group; | ||
387 | } | ||
388 | |||
389 | /* Find the merged set of getopt options, with keys appropiately prefixed. */ | ||
390 | static void | ||
391 | parser_convert (struct parser *parser, const struct argp *argp, int flags) | ||
392 | { | ||
393 | struct parser_convert_state cvt; | ||
394 | |||
395 | cvt.parser = parser; | ||
396 | cvt.short_end = parser->short_opts; | ||
397 | cvt.long_end = parser->long_opts; | ||
398 | cvt.child_inputs_end = parser->child_inputs; | ||
399 | |||
400 | if (flags & ARGP_IN_ORDER) | ||
401 | *cvt.short_end++ = '-'; | ||
402 | else if (flags & ARGP_NO_ARGS) | ||
403 | *cvt.short_end++ = '+'; | ||
404 | *cvt.short_end = '\0'; | ||
405 | |||
406 | cvt.long_end->name = NULL; | ||
407 | |||
408 | parser->argp = argp; | ||
409 | |||
410 | if (argp) | ||
411 | parser->egroup = convert_options (argp, 0, 0, parser->groups, &cvt); | ||
412 | else | ||
413 | parser->egroup = parser->groups; /* No parsers at all! */ | ||
414 | } | ||
415 | |||
416 | /* Lengths of various parser fields which we will allocated. */ | ||
417 | struct parser_sizes | ||
418 | { | ||
419 | size_t short_len; /* Getopt short options string. */ | ||
420 | size_t long_len; /* Getopt long options vector. */ | ||
421 | size_t num_groups; /* Group structures we allocate. */ | ||
422 | size_t num_child_inputs; /* Child input slots. */ | ||
423 | }; | ||
424 | |||
425 | /* For ARGP, increments the NUM_GROUPS field in SZS by the total number of | ||
426 | argp structures descended from it, and the SHORT_LEN & LONG_LEN fields by | ||
427 | the maximum lengths of the resulting merged getopt short options string and | ||
428 | long-options array, respectively. */ | ||
429 | static void | ||
430 | calc_sizes (const struct argp *argp, struct parser_sizes *szs) | ||
431 | { | ||
432 | const struct argp_child *child = argp->children; | ||
433 | const struct argp_option *opt = argp->options; | ||
434 | |||
435 | if (opt || argp->parser) | ||
436 | { | ||
437 | szs->num_groups++; | ||
438 | if (opt) | ||
439 | { | ||
440 | int num_opts = 0; | ||
441 | while (!__option_is_end (opt++)) | ||
442 | num_opts++; | ||
443 | szs->short_len += num_opts * 3; /* opt + up to 2 `:'s */ | ||
444 | szs->long_len += num_opts; | ||
445 | } | ||
446 | } | ||
447 | |||
448 | if (child) | ||
449 | while (child->argp) | ||
450 | { | ||
451 | calc_sizes ((child++)->argp, szs); | ||
452 | szs->num_child_inputs++; | ||
453 | } | ||
454 | } | ||
455 | |||
456 | /* Initializes PARSER to parse ARGP in a manner described by FLAGS. */ | ||
457 | static error_t | ||
458 | parser_init (struct parser *parser, const struct argp *argp, | ||
459 | int argc, char **argv, int flags, void *input) | ||
460 | { | ||
461 | error_t err = 0; | ||
462 | struct group *group; | ||
463 | struct parser_sizes szs; | ||
464 | struct _getopt_data opt_data = _GETOPT_DATA_INITIALIZER; | ||
465 | char *storage; | ||
466 | size_t glen, gsum; | ||
467 | size_t clen, csum; | ||
468 | size_t llen, lsum; | ||
469 | size_t slen, ssum; | ||
470 | |||
471 | szs.short_len = (flags & ARGP_NO_ARGS) ? 0 : 1; | ||
472 | szs.long_len = 0; | ||
473 | szs.num_groups = 0; | ||
474 | szs.num_child_inputs = 0; | ||
475 | |||
476 | if (argp) | ||
477 | calc_sizes (argp, &szs); | ||
478 | |||
479 | /* Lengths of the various bits of storage used by PARSER. */ | ||
480 | glen = (szs.num_groups + 1) * sizeof (struct group); | ||
481 | clen = szs.num_child_inputs * sizeof (void *); | ||
482 | llen = (szs.long_len + 1) * sizeof (struct option); | ||
483 | slen = szs.short_len + 1; | ||
484 | |||
485 | /* Sums of previous lengths, properly aligned. There's no need to | ||
486 | align gsum, since struct group is aligned at least as strictly as | ||
487 | void * (since it contains a void * member). And there's no need | ||
488 | to align lsum, since struct option is aligned at least as | ||
489 | strictly as char. */ | ||
490 | gsum = glen; | ||
491 | csum = alignto (gsum + clen, alignof (struct option)); | ||
492 | lsum = csum + llen; | ||
493 | ssum = lsum + slen; | ||
494 | |||
495 | parser->storage = malloc (ssum); | ||
496 | if (! parser->storage) | ||
497 | return ENOMEM; | ||
498 | |||
499 | storage = parser->storage; | ||
500 | parser->groups = parser->storage; | ||
501 | parser->child_inputs = (void **) (storage + gsum); | ||
502 | parser->long_opts = (struct option *) (storage + csum); | ||
503 | parser->short_opts = storage + lsum; | ||
504 | parser->opt_data = opt_data; | ||
505 | |||
506 | memset (parser->child_inputs, 0, clen); | ||
507 | parser_convert (parser, argp, flags); | ||
508 | |||
509 | memset (&parser->state, 0, sizeof (struct argp_state)); | ||
510 | parser->state.root_argp = parser->argp; | ||
511 | parser->state.argc = argc; | ||
512 | parser->state.argv = argv; | ||
513 | parser->state.flags = flags; | ||
514 | parser->state.err_stream = stderr; | ||
515 | parser->state.out_stream = stdout; | ||
516 | parser->state.next = 0; /* Tell getopt to initialize. */ | ||
517 | parser->state.pstate = parser; | ||
518 | |||
519 | parser->try_getopt = 1; | ||
520 | |||
521 | /* Call each parser for the first time, giving it a chance to propagate | ||
522 | values to child parsers. */ | ||
523 | if (parser->groups < parser->egroup) | ||
524 | parser->groups->input = input; | ||
525 | for (group = parser->groups; | ||
526 | group < parser->egroup && (!err || err == EBADKEY); | ||
527 | group++) | ||
528 | { | ||
529 | if (group->parent) | ||
530 | /* If a child parser, get the initial input value from the parent. */ | ||
531 | group->input = group->parent->child_inputs[group->parent_index]; | ||
532 | |||
533 | if (!group->parser | ||
534 | && group->argp->children && group->argp->children->argp) | ||
535 | /* For the special case where no parsing function is supplied for an | ||
536 | argp, propagate its input to its first child, if any (this just | ||
537 | makes very simple wrapper argps more convenient). */ | ||
538 | group->child_inputs[0] = group->input; | ||
539 | |||
540 | err = group_parse (group, &parser->state, ARGP_KEY_INIT, 0); | ||
541 | } | ||
542 | if (err == EBADKEY) | ||
543 | err = 0; /* Some parser didn't understand. */ | ||
544 | |||
545 | if (err) | ||
546 | return err; | ||
547 | |||
548 | if (parser->state.flags & ARGP_NO_ERRS) | ||
549 | { | ||
550 | parser->opt_data.opterr = 0; | ||
551 | if (parser->state.flags & ARGP_PARSE_ARGV0) | ||
552 | /* getopt always skips ARGV[0], so we have to fake it out. As long | ||
553 | as OPTERR is 0, then it shouldn't actually try to access it. */ | ||
554 | parser->state.argv--, parser->state.argc++; | ||
555 | } | ||
556 | else | ||
557 | parser->opt_data.opterr = 1; /* Print error messages. */ | ||
558 | |||
559 | if (parser->state.argv == argv && argv[0]) | ||
560 | /* There's an argv[0]; use it for messages. */ | ||
561 | parser->state.name = __argp_base_name (argv[0]); | ||
562 | else | ||
563 | parser->state.name = __argp_short_program_name (); | ||
564 | |||
565 | return 0; | ||
566 | } | ||
567 | |||
568 | /* Free any storage consumed by PARSER (but not PARSER itself). */ | ||
569 | static error_t | ||
570 | parser_finalize (struct parser *parser, | ||
571 | error_t err, int arg_ebadkey, int *end_index) | ||
572 | { | ||
573 | struct group *group; | ||
574 | |||
575 | if (err == EBADKEY && arg_ebadkey) | ||
576 | /* Suppress errors generated by unparsed arguments. */ | ||
577 | err = 0; | ||
578 | |||
579 | if (! err) | ||
580 | { | ||
581 | if (parser->state.next == parser->state.argc) | ||
582 | /* We successfully parsed all arguments! Call all the parsers again, | ||
583 | just a few more times... */ | ||
584 | { | ||
585 | for (group = parser->groups; | ||
586 | group < parser->egroup && (!err || err==EBADKEY); | ||
587 | group++) | ||
588 | if (group->args_processed == 0) | ||
589 | err = group_parse (group, &parser->state, ARGP_KEY_NO_ARGS, 0); | ||
590 | for (group = parser->egroup - 1; | ||
591 | group >= parser->groups && (!err || err==EBADKEY); | ||
592 | group--) | ||
593 | err = group_parse (group, &parser->state, ARGP_KEY_END, 0); | ||
594 | |||
595 | if (err == EBADKEY) | ||
596 | err = 0; /* Some parser didn't understand. */ | ||
597 | |||
598 | /* Tell the user that all arguments are parsed. */ | ||
599 | if (end_index) | ||
600 | *end_index = parser->state.next; | ||
601 | } | ||
602 | else if (end_index) | ||
603 | /* Return any remaining arguments to the user. */ | ||
604 | *end_index = parser->state.next; | ||
605 | else | ||
606 | /* No way to return the remaining arguments, they must be bogus. */ | ||
607 | { | ||
608 | if (!(parser->state.flags & ARGP_NO_ERRS) | ||
609 | && parser->state.err_stream) | ||
610 | fprintf (parser->state.err_stream, | ||
611 | dgettext (parser->argp->argp_domain, | ||
612 | "%s: Too many arguments\n"), | ||
613 | parser->state.name); | ||
614 | err = EBADKEY; | ||
615 | } | ||
616 | } | ||
617 | |||
618 | /* Okay, we're all done, with either an error or success; call the parsers | ||
619 | to indicate which one. */ | ||
620 | |||
621 | if (err) | ||
622 | { | ||
623 | /* Maybe print an error message. */ | ||
624 | if (err == EBADKEY) | ||
625 | /* An appropriate message describing what the error was should have | ||
626 | been printed earlier. */ | ||
627 | __argp_state_help (&parser->state, parser->state.err_stream, | ||
628 | ARGP_HELP_STD_ERR); | ||
629 | |||
630 | /* Since we didn't exit, give each parser an error indication. */ | ||
631 | for (group = parser->groups; group < parser->egroup; group++) | ||
632 | group_parse (group, &parser->state, ARGP_KEY_ERROR, 0); | ||
633 | } | ||
634 | else | ||
635 | /* Notify parsers of success, and propagate back values from parsers. */ | ||
636 | { | ||
637 | /* We pass over the groups in reverse order so that child groups are | ||
638 | given a chance to do there processing before passing back a value to | ||
639 | the parent. */ | ||
640 | for (group = parser->egroup - 1 | ||
641 | ; group >= parser->groups && (!err || err == EBADKEY) | ||
642 | ; group--) | ||
643 | err = group_parse (group, &parser->state, ARGP_KEY_SUCCESS, 0); | ||
644 | if (err == EBADKEY) | ||
645 | err = 0; /* Some parser didn't understand. */ | ||
646 | } | ||
647 | |||
648 | /* Call parsers once more, to do any final cleanup. Errors are ignored. */ | ||
649 | for (group = parser->egroup - 1; group >= parser->groups; group--) | ||
650 | group_parse (group, &parser->state, ARGP_KEY_FINI, 0); | ||
651 | |||
652 | if (err == EBADKEY) | ||
653 | err = EINVAL; | ||
654 | |||
655 | free (parser->storage); | ||
656 | |||
657 | return err; | ||
658 | } | ||
659 | |||
660 | /* Call the user parsers to parse the non-option argument VAL, at the current | ||
661 | position, returning any error. The state NEXT pointer is assumed to have | ||
662 | been adjusted (by getopt) to point after this argument; this function will | ||
663 | adjust it correctly to reflect however many args actually end up being | ||
664 | consumed. */ | ||
665 | static error_t | ||
666 | parser_parse_arg (struct parser *parser, char *val) | ||
667 | { | ||
668 | /* Save the starting value of NEXT, first adjusting it so that the arg | ||
669 | we're parsing is again the front of the arg vector. */ | ||
670 | int index = --parser->state.next; | ||
671 | error_t err = EBADKEY; | ||
672 | struct group *group; | ||
673 | int key = 0; /* Which of ARGP_KEY_ARG[S] we used. */ | ||
674 | |||
675 | /* Try to parse the argument in each parser. */ | ||
676 | for (group = parser->groups | ||
677 | ; group < parser->egroup && err == EBADKEY | ||
678 | ; group++) | ||
679 | { | ||
680 | parser->state.next++; /* For ARGP_KEY_ARG, consume the arg. */ | ||
681 | key = ARGP_KEY_ARG; | ||
682 | err = group_parse (group, &parser->state, key, val); | ||
683 | |||
684 | if (err == EBADKEY) | ||
685 | /* This parser doesn't like ARGP_KEY_ARG; try ARGP_KEY_ARGS instead. */ | ||
686 | { | ||
687 | parser->state.next--; /* For ARGP_KEY_ARGS, put back the arg. */ | ||
688 | key = ARGP_KEY_ARGS; | ||
689 | err = group_parse (group, &parser->state, key, 0); | ||
690 | } | ||
691 | } | ||
692 | |||
693 | if (! err) | ||
694 | { | ||
695 | if (key == ARGP_KEY_ARGS) | ||
696 | /* The default for ARGP_KEY_ARGS is to assume that if NEXT isn't | ||
697 | changed by the user, *all* arguments should be considered | ||
698 | consumed. */ | ||
699 | parser->state.next = parser->state.argc; | ||
700 | |||
701 | if (parser->state.next > index) | ||
702 | /* Remember that we successfully processed a non-option | ||
703 | argument -- but only if the user hasn't gotten tricky and set | ||
704 | the clock back. */ | ||
705 | (--group)->args_processed += (parser->state.next - index); | ||
706 | else | ||
707 | /* The user wants to reparse some args, give getopt another try. */ | ||
708 | parser->try_getopt = 1; | ||
709 | } | ||
710 | |||
711 | return err; | ||
712 | } | ||
713 | |||
714 | /* Call the user parsers to parse the option OPT, with argument VAL, at the | ||
715 | current position, returning any error. */ | ||
716 | static error_t | ||
717 | parser_parse_opt (struct parser *parser, int opt, char *val) | ||
718 | { | ||
719 | /* The group key encoded in the high bits; 0 for short opts or | ||
720 | group_number + 1 for long opts. */ | ||
721 | int group_key = opt >> USER_BITS; | ||
722 | error_t err = EBADKEY; | ||
723 | |||
724 | if (group_key == 0) | ||
725 | /* A short option. By comparing OPT's position in SHORT_OPTS to the | ||
726 | various starting positions in each group's SHORT_END field, we can | ||
727 | determine which group OPT came from. */ | ||
728 | { | ||
729 | struct group *group; | ||
730 | char *short_index = strchr (parser->short_opts, opt); | ||
731 | |||
732 | if (short_index) | ||
733 | for (group = parser->groups; group < parser->egroup; group++) | ||
734 | if (group->short_end > short_index) | ||
735 | { | ||
736 | err = group_parse (group, &parser->state, opt, | ||
737 | parser->opt_data.optarg); | ||
738 | break; | ||
739 | } | ||
740 | } | ||
741 | else | ||
742 | /* A long option. We use shifts instead of masking for extracting | ||
743 | the user value in order to preserve the sign. */ | ||
744 | err = | ||
745 | group_parse (&parser->groups[group_key - 1], &parser->state, | ||
746 | (opt << GROUP_BITS) >> GROUP_BITS, | ||
747 | parser->opt_data.optarg); | ||
748 | |||
749 | if (err == EBADKEY) | ||
750 | /* At least currently, an option not recognized is an error in the | ||
751 | parser, because we pre-compute which parser is supposed to deal | ||
752 | with each option. */ | ||
753 | { | ||
754 | static const char bad_key_err[] = | ||
755 | N_("(PROGRAM ERROR) Option should have been recognized!?"); | ||
756 | if (group_key == 0) | ||
757 | __argp_error (&parser->state, "-%c: %s", opt, | ||
758 | dgettext (parser->argp->argp_domain, bad_key_err)); | ||
759 | else | ||
760 | { | ||
761 | struct option *long_opt = parser->long_opts; | ||
762 | while (long_opt->val != opt && long_opt->name) | ||
763 | long_opt++; | ||
764 | __argp_error (&parser->state, "--%s: %s", | ||
765 | long_opt->name ? long_opt->name : "???", | ||
766 | dgettext (parser->argp->argp_domain, bad_key_err)); | ||
767 | } | ||
768 | } | ||
769 | |||
770 | return err; | ||
771 | } | ||
772 | |||
773 | /* Parse the next argument in PARSER (as indicated by PARSER->state.next). | ||
774 | Any error from the parsers is returned, and *ARGP_EBADKEY indicates | ||
775 | whether a value of EBADKEY is due to an unrecognized argument (which is | ||
776 | generally not fatal). */ | ||
777 | static error_t | ||
778 | parser_parse_next (struct parser *parser, int *arg_ebadkey) | ||
779 | { | ||
780 | int opt; | ||
781 | error_t err = 0; | ||
782 | |||
783 | if (parser->state.quoted && parser->state.next < parser->state.quoted) | ||
784 | /* The next argument pointer has been moved to before the quoted | ||
785 | region, so pretend we never saw the quoting `--', and give getopt | ||
786 | another chance. If the user hasn't removed it, getopt will just | ||
787 | process it again. */ | ||
788 | parser->state.quoted = 0; | ||
789 | |||
790 | if (parser->try_getopt && !parser->state.quoted) | ||
791 | /* Give getopt a chance to parse this. */ | ||
792 | { | ||
793 | /* Put it back in OPTIND for getopt. */ | ||
794 | parser->opt_data.optind = parser->state.next; | ||
795 | /* Distinguish KEY_ERR from a real option. */ | ||
796 | parser->opt_data.optopt = KEY_END; | ||
797 | if (parser->state.flags & ARGP_LONG_ONLY) | ||
798 | opt = _getopt_long_only_r (parser->state.argc, parser->state.argv, | ||
799 | parser->short_opts, parser->long_opts, 0, | ||
800 | &parser->opt_data); | ||
801 | else | ||
802 | opt = _getopt_long_r (parser->state.argc, parser->state.argv, | ||
803 | parser->short_opts, parser->long_opts, 0, | ||
804 | &parser->opt_data); | ||
805 | /* And see what getopt did. */ | ||
806 | parser->state.next = parser->opt_data.optind; | ||
807 | |||
808 | if (opt == KEY_END) | ||
809 | /* Getopt says there are no more options, so stop using | ||
810 | getopt; we'll continue if necessary on our own. */ | ||
811 | { | ||
812 | parser->try_getopt = 0; | ||
813 | if (parser->state.next > 1 | ||
814 | && strcmp (parser->state.argv[parser->state.next - 1], QUOTE) | ||
815 | == 0) | ||
816 | /* Not only is this the end of the options, but it's a | ||
817 | `quoted' region, which may have args that *look* like | ||
818 | options, so we definitely shouldn't try to use getopt past | ||
819 | here, whatever happens. */ | ||
820 | parser->state.quoted = parser->state.next; | ||
821 | } | ||
822 | else if (opt == KEY_ERR && parser->opt_data.optopt != KEY_END) | ||
823 | /* KEY_ERR can have the same value as a valid user short | ||
824 | option, but in the case of a real error, getopt sets OPTOPT | ||
825 | to the offending character, which can never be KEY_END. */ | ||
826 | { | ||
827 | *arg_ebadkey = 0; | ||
828 | return EBADKEY; | ||
829 | } | ||
830 | } | ||
831 | else | ||
832 | opt = KEY_END; | ||
833 | |||
834 | if (opt == KEY_END) | ||
835 | { | ||
836 | /* We're past what getopt considers the options. */ | ||
837 | if (parser->state.next >= parser->state.argc | ||
838 | || (parser->state.flags & ARGP_NO_ARGS)) | ||
839 | /* Indicate that we're done. */ | ||
840 | { | ||
841 | *arg_ebadkey = 1; | ||
842 | return EBADKEY; | ||
843 | } | ||
844 | else | ||
845 | /* A non-option arg; simulate what getopt might have done. */ | ||
846 | { | ||
847 | opt = KEY_ARG; | ||
848 | parser->opt_data.optarg = parser->state.argv[parser->state.next++]; | ||
849 | } | ||
850 | } | ||
851 | |||
852 | if (opt == KEY_ARG) | ||
853 | /* A non-option argument; try each parser in turn. */ | ||
854 | err = parser_parse_arg (parser, parser->opt_data.optarg); | ||
855 | else | ||
856 | err = parser_parse_opt (parser, opt, parser->opt_data.optarg); | ||
857 | |||
858 | if (err == EBADKEY) | ||
859 | *arg_ebadkey = (opt == KEY_END || opt == KEY_ARG); | ||
860 | |||
861 | return err; | ||
862 | } | ||
863 | |||
864 | /* Parse the options strings in ARGC & ARGV according to the argp in ARGP. | ||
865 | FLAGS is one of the ARGP_ flags above. If END_INDEX is non-NULL, the | ||
866 | index in ARGV of the first unparsed option is returned in it. If an | ||
867 | unknown option is present, EINVAL is returned; if some parser routine | ||
868 | returned a non-zero value, it is returned; otherwise 0 is returned. */ | ||
869 | error_t | ||
870 | __argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags, | ||
871 | int *end_index, void *input) | ||
872 | { | ||
873 | error_t err; | ||
874 | struct parser parser; | ||
875 | |||
876 | /* If true, then err == EBADKEY is a result of a non-option argument failing | ||
877 | to be parsed (which in some cases isn't actually an error). */ | ||
878 | int arg_ebadkey = 0; | ||
879 | |||
880 | #ifndef _LIBC | ||
881 | if (!(flags & ARGP_PARSE_ARGV0)) | ||
882 | { | ||
883 | #ifdef HAVE_DECL_PROGRAM_INVOCATION_NAME | ||
884 | if (!program_invocation_name) | ||
885 | program_invocation_name = argv[0]; | ||
886 | #endif | ||
887 | #ifdef HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME | ||
888 | if (!program_invocation_short_name) | ||
889 | program_invocation_short_name = __argp_base_name (argv[0]); | ||
890 | #endif | ||
891 | } | ||
892 | #endif | ||
893 | |||
894 | if (! (flags & ARGP_NO_HELP)) | ||
895 | /* Add our own options. */ | ||
896 | { | ||
897 | struct argp_child *child = alloca (4 * sizeof (struct argp_child)); | ||
898 | struct argp *top_argp = alloca (sizeof (struct argp)); | ||
899 | |||
900 | /* TOP_ARGP has no options, it just serves to group the user & default | ||
901 | argps. */ | ||
902 | memset (top_argp, 0, sizeof (*top_argp)); | ||
903 | top_argp->children = child; | ||
904 | |||
905 | memset (child, 0, 4 * sizeof (struct argp_child)); | ||
906 | |||
907 | if (argp) | ||
908 | (child++)->argp = argp; | ||
909 | (child++)->argp = &argp_default_argp; | ||
910 | if (argp_program_version || argp_program_version_hook) | ||
911 | (child++)->argp = &argp_version_argp; | ||
912 | child->argp = 0; | ||
913 | |||
914 | argp = top_argp; | ||
915 | } | ||
916 | |||
917 | /* Construct a parser for these arguments. */ | ||
918 | err = parser_init (&parser, argp, argc, argv, flags, input); | ||
919 | |||
920 | if (! err) | ||
921 | /* Parse! */ | ||
922 | { | ||
923 | while (! err) | ||
924 | err = parser_parse_next (&parser, &arg_ebadkey); | ||
925 | err = parser_finalize (&parser, err, arg_ebadkey, end_index); | ||
926 | } | ||
927 | |||
928 | return err; | ||
929 | } | ||
930 | #ifdef weak_alias | ||
931 | weak_alias (__argp_parse, argp_parse) | ||
932 | #endif | ||
933 | |||
934 | /* Return the input field for ARGP in the parser corresponding to STATE; used | ||
935 | by the help routines. */ | ||
936 | void * | ||
937 | __argp_input (const struct argp *argp, const struct argp_state *state) | ||
938 | { | ||
939 | if (state) | ||
940 | { | ||
941 | struct group *group; | ||
942 | struct parser *parser = state->pstate; | ||
943 | |||
944 | for (group = parser->groups; group < parser->egroup; group++) | ||
945 | if (group->argp == argp) | ||
946 | return group->input; | ||
947 | } | ||
948 | |||
949 | return 0; | ||
950 | } | ||
951 | #ifdef weak_alias | ||
952 | weak_alias (__argp_input, _argp_input) | ||
953 | #endif |
mailbox/argp-pin.c
deleted
100644 → 0
1 | /* Full and short program names for argp module | ||
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 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 | #ifdef HAVE_CONFIG_H | ||
19 | # include <config.h> | ||
20 | #endif | ||
21 | |||
22 | #ifndef HAVE_PROGRAM_INVOCATION_SHORT_NAME | ||
23 | char *program_invocation_short_name = 0; | ||
24 | #endif | ||
25 | #ifndef HAVE_PROGRAM_INVOCATION_NAME | ||
26 | char *program_invocation_name = 0; | ||
27 | #endif | ||
28 |
mailbox/argp-pv.c
deleted
100644 → 0
1 | /* Default definition for ARGP_PROGRAM_VERSION. | ||
2 | Copyright (C) 1996, 1997, 1999, 2006 Free Software Foundation, Inc. | ||
3 | This file is part of the GNU C Library. | ||
4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. | ||
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 | /* If set by the user program to a non-zero value, then a default option | ||
21 | --version is added (unless the ARGP_NO_HELP flag is used), which will | ||
22 | print this string followed by a newline and exit (unless the | ||
23 | ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */ | ||
24 | const char *argp_program_version; |
mailbox/argp-pvh.c
deleted
100644 → 0
1 | /* Default definition for ARGP_PROGRAM_VERSION_HOOK. | ||
2 | Copyright (C) 1996, 1997, 1999, 2004 Free Software Foundation, Inc. | ||
3 | This file is part of the GNU C Library. | ||
4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. | ||
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 HAVE_CONFIG_H | ||
21 | # include <config.h> | ||
22 | #endif | ||
23 | |||
24 | #include "argp.h" | ||
25 | |||
26 | /* If set by the user program to a non-zero value, then a default option | ||
27 | --version is added (unless the ARGP_NO_HELP flag is used), which calls | ||
28 | this function with a stream to print the version to and a pointer to the | ||
29 | current parsing state, and then exits (unless the ARGP_NO_EXIT flag is | ||
30 | used). This variable takes precedent over ARGP_PROGRAM_VERSION. */ | ||
31 | void (*argp_program_version_hook) (FILE *stream, struct argp_state *state) = NULL; |
mailbox/argp-xinl.c
deleted
100644 → 0
1 | /* Real definitions for extern inline functions in argp.h | ||
2 | Copyright (C) 1997, 1998, 2004 Free Software Foundation, Inc. | ||
3 | This file is part of the GNU C Library. | ||
4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. | ||
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 HAVE_CONFIG_H | ||
21 | # include <config.h> | ||
22 | #endif | ||
23 | |||
24 | #if defined _LIBC || defined HAVE_FEATURES_H | ||
25 | # include <features.h> | ||
26 | #endif | ||
27 | |||
28 | #ifndef __USE_EXTERN_INLINES | ||
29 | # define __USE_EXTERN_INLINES 1 | ||
30 | #endif | ||
31 | #define ARGP_EI | ||
32 | #undef __OPTIMIZE__ | ||
33 | #define __OPTIMIZE__ 1 | ||
34 | #include "argp.h" | ||
35 | |||
36 | /* Add weak aliases. */ | ||
37 | #if _LIBC - 0 && defined (weak_alias) | ||
38 | |||
39 | weak_alias (__argp_usage, argp_usage) | ||
40 | weak_alias (__option_is_short, _option_is_short) | ||
41 | weak_alias (__option_is_end, _option_is_end) | ||
42 | |||
43 | #endif |
mailbox/argp.h
deleted
100644 → 0
1 | /* Hierarchial argument parsing, layered over getopt. | ||
2 | Copyright (C) 1995-1999,2003-2006 Free Software Foundation, Inc. | ||
3 | This file is part of the GNU C Library. | ||
4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. | ||
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 _ARGP_H | ||
21 | #define _ARGP_H | ||
22 | |||
23 | #include <stdio.h> | ||
24 | #include <ctype.h> | ||
25 | #include <getopt.h> | ||
26 | #include <limits.h> | ||
27 | |||
28 | #define __need_error_t | ||
29 | #include <errno.h> | ||
30 | |||
31 | #ifndef __THROW | ||
32 | # define __THROW | ||
33 | #endif | ||
34 | #ifndef __NTH | ||
35 | # define __NTH(fct) fct __THROW | ||
36 | #endif | ||
37 | |||
38 | #ifndef __attribute__ | ||
39 | /* This feature is available in gcc versions 2.5 and later. */ | ||
40 | # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__ | ||
41 | # define __attribute__(Spec) /* empty */ | ||
42 | # endif | ||
43 | /* The __-protected variants of `format' and `printf' attributes | ||
44 | are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ | ||
45 | # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) || __STRICT_ANSI__ | ||
46 | # define __format__ format | ||
47 | # define __printf__ printf | ||
48 | # endif | ||
49 | #endif | ||
50 | |||
51 | /* GCC 2.95 and later have "__restrict"; C99 compilers have | ||
52 | "restrict", and "configure" may have defined "restrict". */ | ||
53 | #ifndef __restrict | ||
54 | # if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__)) | ||
55 | # if defined restrict || 199901L <= __STDC_VERSION__ | ||
56 | # define __restrict restrict | ||
57 | # else | ||
58 | # define __restrict | ||
59 | # endif | ||
60 | # endif | ||
61 | #endif | ||
62 | |||
63 | #ifndef __error_t_defined | ||
64 | typedef int error_t; | ||
65 | # define __error_t_defined | ||
66 | #endif | ||
67 | |||
68 | #ifdef __cplusplus | ||
69 | extern "C" { | ||
70 | #endif | ||
71 | |||
72 | /* A description of a particular option. A pointer to an array of | ||
73 | these is passed in the OPTIONS field of an argp structure. Each option | ||
74 | entry can correspond to one long option and/or one short option; more | ||
75 | names for the same option can be added by following an entry in an option | ||
76 | array with options having the OPTION_ALIAS flag set. */ | ||
77 | struct argp_option | ||
78 | { | ||
79 | /* The long option name. For more than one name for the same option, you | ||
80 | can use following options with the OPTION_ALIAS flag set. */ | ||
81 | const char *name; | ||
82 | |||
83 | /* What key is returned for this option. If > 0 and printable, then it's | ||
84 | also accepted as a short option. */ | ||
85 | int key; | ||
86 | |||
87 | /* If non-NULL, this is the name of the argument associated with this | ||
88 | option, which is required unless the OPTION_ARG_OPTIONAL flag is set. */ | ||
89 | const char *arg; | ||
90 | |||
91 | /* OPTION_ flags. */ | ||
92 | int flags; | ||
93 | |||
94 | /* The doc string for this option. If both NAME and KEY are 0, This string | ||
95 | will be printed outdented from the normal option column, making it | ||
96 | useful as a group header (it will be the first thing printed in its | ||
97 | group); in this usage, it's conventional to end the string with a `:'. | ||
98 | |||
99 | Write the initial value as N_("TEXT") if you want xgettext to collect | ||
100 | it into a POT file. */ | ||
101 | const char *doc; | ||
102 | |||
103 | /* The group this option is in. In a long help message, options are sorted | ||
104 | alphabetically within each group, and the groups presented in the order | ||
105 | 0, 1, 2, ..., n, -m, ..., -2, -1. Every entry in an options array with | ||
106 | if this field 0 will inherit the group number of the previous entry, or | ||
107 | zero if it's the first one, unless its a group header (NAME and KEY both | ||
108 | 0), in which case, the previous entry + 1 is the default. Automagic | ||
109 | options such as --help are put into group -1. */ | ||
110 | int group; | ||
111 | }; | ||
112 | |||
113 | /* The argument associated with this option is optional. */ | ||
114 | #define OPTION_ARG_OPTIONAL 0x1 | ||
115 | |||
116 | /* This option isn't displayed in any help messages. */ | ||
117 | #define OPTION_HIDDEN 0x2 | ||
118 | |||
119 | /* This option is an alias for the closest previous non-alias option. This | ||
120 | means that it will be displayed in the same help entry, and will inherit | ||
121 | fields other than NAME and KEY from the aliased option. */ | ||
122 | #define OPTION_ALIAS 0x4 | ||
123 | |||
124 | /* This option isn't actually an option (and so should be ignored by the | ||
125 | actual option parser), but rather an arbitrary piece of documentation that | ||
126 | should be displayed in much the same manner as the options. If this flag | ||
127 | is set, then the option NAME field is displayed unmodified (e.g., no `--' | ||
128 | prefix is added) at the left-margin (where a *short* option would normally | ||
129 | be displayed), and the documentation string in the normal place. The NAME | ||
130 | field will be translated using gettext, unless OPTION_NO_TRANS is set (see | ||
131 | below). For purposes of sorting, any leading whitespace and punctuation is | ||
132 | ignored, except that if the first non-whitespace character is not `-', this | ||
133 | entry is displayed after all options (and OPTION_DOC entries with a leading | ||
134 | `-') in the same group. */ | ||
135 | #define OPTION_DOC 0x8 | ||
136 | |||
137 | /* This option shouldn't be included in `long' usage messages (but is still | ||
138 | included in help messages). This is mainly intended for options that are | ||
139 | completely documented in an argp's ARGS_DOC field, in which case including | ||
140 | the option in the generic usage list would be redundant. For instance, | ||
141 | if ARGS_DOC is "FOO BAR\n-x BLAH", and the `-x' option's purpose is to | ||
142 | distinguish these two cases, -x should probably be marked | ||
143 | OPTION_NO_USAGE. */ | ||
144 | #define OPTION_NO_USAGE 0x10 | ||
145 | |||
146 | /* Valid only in conjunction with OPTION_DOC. This option disables translation | ||
147 | of option name. */ | ||
148 | #define OPTION_NO_TRANS 0x20 | ||
149 | |||
150 | |||
151 | struct argp; /* fwd declare this type */ | ||
152 | struct argp_state; /* " */ | ||
153 | struct argp_child; /* " */ | ||
154 | |||
155 | /* The type of a pointer to an argp parsing function. */ | ||
156 | typedef error_t (*argp_parser_t) (int key, char *arg, | ||
157 | struct argp_state *state); | ||
158 | |||
159 | /* What to return for unrecognized keys. For special ARGP_KEY_ keys, such | ||
160 | returns will simply be ignored. For user keys, this error will be turned | ||
161 | into EINVAL (if the call to argp_parse is such that errors are propagated | ||
162 | back to the user instead of exiting); returning EINVAL itself would result | ||
163 | in an immediate stop to parsing in *all* cases. */ | ||
164 | #define ARGP_ERR_UNKNOWN E2BIG /* Hurd should never need E2BIG. XXX */ | ||
165 | |||
166 | /* Special values for the KEY argument to an argument parsing function. | ||
167 | ARGP_ERR_UNKNOWN should be returned if they aren't understood. | ||
168 | |||
169 | The sequence of keys to a parsing function is either (where each | ||
170 | uppercased word should be prefixed by `ARGP_KEY_' and opt is a user key): | ||
171 | |||
172 | INIT opt... NO_ARGS END SUCCESS -- No non-option arguments at all | ||
173 | or INIT (opt | ARG)... END SUCCESS -- All non-option args parsed | ||
174 | or INIT (opt | ARG)... SUCCESS -- Some non-option arg unrecognized | ||
175 | |||
176 | The third case is where every parser returned ARGP_KEY_UNKNOWN for an | ||
177 | argument, in which case parsing stops at that argument (returning the | ||
178 | unparsed arguments to the caller of argp_parse if requested, or stopping | ||
179 | with an error message if not). | ||
180 | |||
181 | If an error occurs (either detected by argp, or because the parsing | ||
182 | function returned an error value), then the parser is called with | ||
183 | ARGP_KEY_ERROR, and no further calls are made. */ | ||
184 | |||
185 | /* This is not an option at all, but rather a command line argument. If a | ||
186 | parser receiving this key returns success, the fact is recorded, and the | ||
187 | ARGP_KEY_NO_ARGS case won't be used. HOWEVER, if while processing the | ||
188 | argument, a parser function decrements the NEXT field of the state it's | ||
189 | passed, the option won't be considered processed; this is to allow you to | ||
190 | actually modify the argument (perhaps into an option), and have it | ||
191 | processed again. */ | ||
192 | #define ARGP_KEY_ARG 0 | ||
193 | /* There are remaining arguments not parsed by any parser, which may be found | ||
194 | starting at (STATE->argv + STATE->next). If success is returned, but | ||
195 | STATE->next left untouched, it's assumed that all arguments were consume, | ||
196 | otherwise, the parser should adjust STATE->next to reflect any arguments | ||
197 | consumed. */ | ||
198 | #define ARGP_KEY_ARGS 0x1000006 | ||
199 | /* There are no more command line arguments at all. */ | ||
200 | #define ARGP_KEY_END 0x1000001 | ||
201 | /* Because it's common to want to do some special processing if there aren't | ||
202 | any non-option args, user parsers are called with this key if they didn't | ||
203 | successfully process any non-option arguments. Called just before | ||
204 | ARGP_KEY_END (where more general validity checks on previously parsed | ||
205 | arguments can take place). */ | ||
206 | #define ARGP_KEY_NO_ARGS 0x1000002 | ||
207 | /* Passed in before any parsing is done. Afterwards, the values of each | ||
208 | element of the CHILD_INPUT field, if any, in the state structure is | ||
209 | copied to each child's state to be the initial value of the INPUT field. */ | ||
210 | #define ARGP_KEY_INIT 0x1000003 | ||
211 | /* Use after all other keys, including SUCCESS & END. */ | ||
212 | #define ARGP_KEY_FINI 0x1000007 | ||
213 | /* Passed in when parsing has successfully been completed (even if there are | ||
214 | still arguments remaining). */ | ||
215 | #define ARGP_KEY_SUCCESS 0x1000004 | ||
216 | /* Passed in if an error occurs. */ | ||
217 | #define ARGP_KEY_ERROR 0x1000005 | ||
218 | |||
219 | /* An argp structure contains a set of options declarations, a function to | ||
220 | deal with parsing one, documentation string, a possible vector of child | ||
221 | argp's, and perhaps a function to filter help output. When actually | ||
222 | parsing options, getopt is called with the union of all the argp | ||
223 | structures chained together through their CHILD pointers, with conflicts | ||
224 | being resolved in favor of the first occurrence in the chain. */ | ||
225 | struct argp | ||
226 | { | ||
227 | /* An array of argp_option structures, terminated by an entry with both | ||
228 | NAME and KEY having a value of 0. */ | ||
229 | const struct argp_option *options; | ||
230 | |||
231 | /* What to do with an option from this structure. KEY is the key | ||
232 | associated with the option, and ARG is any associated argument (NULL if | ||
233 | none was supplied). If KEY isn't understood, ARGP_ERR_UNKNOWN should be | ||
234 | returned. If a non-zero, non-ARGP_ERR_UNKNOWN value is returned, then | ||
235 | parsing is stopped immediately, and that value is returned from | ||
236 | argp_parse(). For special (non-user-supplied) values of KEY, see the | ||
237 | ARGP_KEY_ definitions below. */ | ||
238 | argp_parser_t parser; | ||
239 | |||
240 | /* A string describing what other arguments are wanted by this program. It | ||
241 | is only used by argp_usage to print the `Usage:' message. If it | ||
242 | contains newlines, the strings separated by them are considered | ||
243 | alternative usage patterns, and printed on separate lines (lines after | ||
244 | the first are prefix by ` or: ' instead of `Usage:'). */ | ||
245 | const char *args_doc; | ||
246 | |||
247 | /* If non-NULL, a string containing extra text to be printed before and | ||
248 | after the options in a long help message (separated by a vertical tab | ||
249 | `\v' character). | ||
250 | Write the initial value as N_("BEFORE-TEXT") "\v" N_("AFTER-TEXT") if | ||
251 | you want xgettext to collect the two pieces of text into a POT file. */ | ||
252 | const char *doc; | ||
253 | |||
254 | /* A vector of argp_children structures, terminated by a member with a 0 | ||
255 | argp field, pointing to child argps should be parsed with this one. Any | ||
256 | conflicts are resolved in favor of this argp, or early argps in the | ||
257 | CHILDREN list. This field is useful if you use libraries that supply | ||
258 | their own argp structure, which you want to use in conjunction with your | ||
259 | own. */ | ||
260 | const struct argp_child *children; | ||
261 | |||
262 | /* If non-zero, this should be a function to filter the output of help | ||
263 | messages. KEY is either a key from an option, in which case TEXT is | ||
264 | that option's help text, or a special key from the ARGP_KEY_HELP_ | ||
265 | defines, below, describing which other help text TEXT is. The function | ||
266 | should return either TEXT, if it should be used as-is, a replacement | ||
267 | string, which should be malloced, and will be freed by argp, or NULL, | ||
268 | meaning `print nothing'. The value for TEXT is *after* any translation | ||
269 | has been done, so if any of the replacement text also needs translation, | ||
270 | that should be done by the filter function. INPUT is either the input | ||
271 | supplied to argp_parse, or NULL, if argp_help was called directly. */ | ||
272 | char *(*help_filter) (int __key, const char *__text, void *__input); | ||
273 | |||
274 | /* If non-zero the strings used in the argp library are translated using | ||
275 | the domain described by this string. Otherwise the currently installed | ||
276 | default domain is used. */ | ||
277 | const char *argp_domain; | ||
278 | }; | ||
279 | |||
280 | /* Possible KEY arguments to a help filter function. */ | ||
281 | #define ARGP_KEY_HELP_PRE_DOC 0x2000001 /* Help text preceeding options. */ | ||
282 | #define ARGP_KEY_HELP_POST_DOC 0x2000002 /* Help text following options. */ | ||
283 | #define ARGP_KEY_HELP_HEADER 0x2000003 /* Option header string. */ | ||
284 | #define ARGP_KEY_HELP_EXTRA 0x2000004 /* After all other documentation; | ||
285 | TEXT is NULL for this key. */ | ||
286 | /* Explanatory note emitted when duplicate option arguments have been | ||
287 | suppressed. */ | ||
288 | #define ARGP_KEY_HELP_DUP_ARGS_NOTE 0x2000005 | ||
289 | #define ARGP_KEY_HELP_ARGS_DOC 0x2000006 /* Argument doc string. */ | ||
290 | |||
291 | /* When an argp has a non-zero CHILDREN field, it should point to a vector of | ||
292 | argp_child structures, each of which describes a subsidiary argp. */ | ||
293 | struct argp_child | ||
294 | { | ||
295 | /* The child parser. */ | ||
296 | const struct argp *argp; | ||
297 | |||
298 | /* Flags for this child. */ | ||
299 | int flags; | ||
300 | |||
301 | /* If non-zero, an optional header to be printed in help output before the | ||
302 | child options. As a side-effect, a non-zero value forces the child | ||
303 | options to be grouped together; to achieve this effect without actually | ||
304 | printing a header string, use a value of "". */ | ||
305 | const char *header; | ||
306 | |||
307 | /* Where to group the child options relative to the other (`consolidated') | ||
308 | options in the parent argp; the values are the same as the GROUP field | ||
309 | in argp_option structs, but all child-groupings follow parent options at | ||
310 | a particular group level. If both this field and HEADER are zero, then | ||
311 | they aren't grouped at all, but rather merged with the parent options | ||
312 | (merging the child's grouping levels with the parents). */ | ||
313 | int group; | ||
314 | }; | ||
315 | |||
316 | /* Parsing state. This is provided to parsing functions called by argp, | ||
317 | which may examine and, as noted, modify fields. */ | ||
318 | struct argp_state | ||
319 | { | ||
320 | /* The top level ARGP being parsed. */ | ||
321 | const struct argp *root_argp; | ||
322 | |||
323 | /* The argument vector being parsed. May be modified. */ | ||
324 | int argc; | ||
325 | char **argv; | ||
326 | |||
327 | /* The index in ARGV of the next arg that to be parsed. May be modified. */ | ||
328 | int next; | ||
329 | |||
330 | /* The flags supplied to argp_parse. May be modified. */ | ||
331 | unsigned flags; | ||
332 | |||
333 | /* While calling a parsing function with a key of ARGP_KEY_ARG, this is the | ||
334 | number of the current arg, starting at zero, and incremented after each | ||
335 | such call returns. At all other times, this is the number of such | ||
336 | arguments that have been processed. */ | ||
337 | unsigned arg_num; | ||
338 | |||
339 | /* If non-zero, the index in ARGV of the first argument following a special | ||
340 | `--' argument (which prevents anything following being interpreted as an | ||
341 | option). Only set once argument parsing has proceeded past this point. */ | ||
342 | int quoted; | ||
343 | |||
344 | /* An arbitrary pointer passed in from the user. */ | ||
345 | void *input; | ||
346 | /* Values to pass to child parsers. This vector will be the same length as | ||
347 | the number of children for the current parser. */ | ||
348 | void **child_inputs; | ||
349 | |||
350 | /* For the parser's use. Initialized to 0. */ | ||
351 | void *hook; | ||
352 | |||
353 | /* The name used when printing messages. This is initialized to ARGV[0], | ||
354 | or PROGRAM_INVOCATION_NAME if that is unavailable. */ | ||
355 | char *name; | ||
356 | |||
357 | /* Streams used when argp prints something. */ | ||
358 | FILE *err_stream; /* For errors; initialized to stderr. */ | ||
359 | FILE *out_stream; /* For information; initialized to stdout. */ | ||
360 | |||
361 | void *pstate; /* Private, for use by argp. */ | ||
362 | }; | ||
363 | |||
364 | /* Flags for argp_parse (note that the defaults are those that are | ||
365 | convenient for program command line parsing): */ | ||
366 | |||
367 | /* Don't ignore the first element of ARGV. Normally (and always unless | ||
368 | ARGP_NO_ERRS is set) the first element of the argument vector is | ||
369 | skipped for option parsing purposes, as it corresponds to the program name | ||
370 | in a command line. */ | ||
371 | #define ARGP_PARSE_ARGV0 0x01 | ||
372 | |||
373 | /* Don't print error messages for unknown options to stderr; unless this flag | ||
374 | is set, ARGP_PARSE_ARGV0 is ignored, as ARGV[0] is used as the program | ||
375 | name in the error messages. This flag implies ARGP_NO_EXIT (on the | ||
376 | assumption that silent exiting upon errors is bad behaviour). */ | ||
377 | #define ARGP_NO_ERRS 0x02 | ||
378 | |||
379 | /* Don't parse any non-option args. Normally non-option args are parsed by | ||
380 | calling the parse functions with a key of ARGP_KEY_ARG, and the actual arg | ||
381 | as the value. Since it's impossible to know which parse function wants to | ||
382 | handle it, each one is called in turn, until one returns 0 or an error | ||
383 | other than ARGP_ERR_UNKNOWN; if an argument is handled by no one, the | ||
384 | argp_parse returns prematurely (but with a return value of 0). If all | ||
385 | args have been parsed without error, all parsing functions are called one | ||
386 | last time with a key of ARGP_KEY_END. This flag needn't normally be set, | ||
387 | as the normal behavior is to stop parsing as soon as some argument can't | ||
388 | be handled. */ | ||
389 | #define ARGP_NO_ARGS 0x04 | ||
390 | |||
391 | /* Parse options and arguments in the same order they occur on the command | ||
392 | line -- normally they're rearranged so that all options come first. */ | ||
393 | #define ARGP_IN_ORDER 0x08 | ||
394 | |||
395 | /* Don't provide the standard long option --help, which causes usage and | ||
396 | option help information to be output to stdout, and exit (0) called. */ | ||
397 | #define ARGP_NO_HELP 0x10 | ||
398 | |||
399 | /* Don't exit on errors (they may still result in error messages). */ | ||
400 | #define ARGP_NO_EXIT 0x20 | ||
401 | |||
402 | /* Use the gnu getopt `long-only' rules for parsing arguments. */ | ||
403 | #define ARGP_LONG_ONLY 0x40 | ||
404 | |||
405 | /* Turns off any message-printing/exiting options. */ | ||
406 | #define ARGP_SILENT (ARGP_NO_EXIT | ARGP_NO_ERRS | ARGP_NO_HELP) | ||
407 | |||
408 | /* Parse the options strings in ARGC & ARGV according to the options in ARGP. | ||
409 | FLAGS is one of the ARGP_ flags above. If ARG_INDEX is non-NULL, the | ||
410 | index in ARGV of the first unparsed option is returned in it. If an | ||
411 | unknown option is present, ARGP_ERR_UNKNOWN is returned; if some parser | ||
412 | routine returned a non-zero value, it is returned; otherwise 0 is | ||
413 | returned. This function may also call exit unless the ARGP_NO_HELP flag | ||
414 | is set. INPUT is a pointer to a value to be passed in to the parser. */ | ||
415 | extern error_t argp_parse (const struct argp *__restrict __argp, | ||
416 | int __argc, char **__restrict __argv, | ||
417 | unsigned __flags, int *__restrict __arg_index, | ||
418 | void *__restrict __input); | ||
419 | extern error_t __argp_parse (const struct argp *__restrict __argp, | ||
420 | int __argc, char **__restrict __argv, | ||
421 | unsigned __flags, int *__restrict __arg_index, | ||
422 | void *__restrict __input); | ||
423 | |||
424 | /* Global variables. */ | ||
425 | |||
426 | /* GNULIB makes sure both program_invocation_name and | ||
427 | program_invocation_short_name are available */ | ||
428 | #ifdef GNULIB_PROGRAM_INVOCATION_NAME | ||
429 | extern char *program_invocation_name; | ||
430 | # undef HAVE_DECL_PROGRAM_INVOCATION_NAME | ||
431 | # define HAVE_DECL_PROGRAM_INVOCATION_NAME 1 | ||
432 | #endif | ||
433 | |||
434 | #ifdef GNULIB_PROGRAM_INVOCATION_SHORT_NAME | ||
435 | extern char *program_invocation_short_name; | ||
436 | # undef HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME | ||
437 | # define HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME 1 | ||
438 | #endif | ||
439 | |||
440 | /* If defined or set by the user program to a non-zero value, then a default | ||
441 | option --version is added (unless the ARGP_NO_HELP flag is used), which | ||
442 | will print this string followed by a newline and exit (unless the | ||
443 | ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */ | ||
444 | extern const char *argp_program_version; | ||
445 | |||
446 | /* If defined or set by the user program to a non-zero value, then a default | ||
447 | option --version is added (unless the ARGP_NO_HELP flag is used), which | ||
448 | calls this function with a stream to print the version to and a pointer to | ||
449 | the current parsing state, and then exits (unless the ARGP_NO_EXIT flag is | ||
450 | used). This variable takes precedent over ARGP_PROGRAM_VERSION. */ | ||
451 | extern void (*argp_program_version_hook) (FILE *__restrict __stream, | ||
452 | struct argp_state *__restrict | ||
453 | __state); | ||
454 | |||
455 | /* If defined or set by the user program, it should point to string that is | ||
456 | the bug-reporting address for the program. It will be printed by | ||
457 | argp_help if the ARGP_HELP_BUG_ADDR flag is set (as it is by various | ||
458 | standard help messages), embedded in a sentence that says something like | ||
459 | `Report bugs to ADDR.'. */ | ||
460 | extern const char *argp_program_bug_address; | ||
461 | |||
462 | /* The exit status that argp will use when exiting due to a parsing error. | ||
463 | If not defined or set by the user program, this defaults to EX_USAGE from | ||
464 | <sysexits.h>. */ | ||
465 | extern error_t argp_err_exit_status; | ||
466 | |||
467 | /* Flags for argp_help. */ | ||
468 | #define ARGP_HELP_USAGE 0x01 /* a Usage: message. */ | ||
469 | #define ARGP_HELP_SHORT_USAGE 0x02 /* " but don't actually print options. */ | ||
470 | #define ARGP_HELP_SEE 0x04 /* a `Try ... for more help' message. */ | ||
471 | #define ARGP_HELP_LONG 0x08 /* a long help message. */ | ||
472 | #define ARGP_HELP_PRE_DOC 0x10 /* doc string preceding long help. */ | ||
473 | #define ARGP_HELP_POST_DOC 0x20 /* doc string following long help. */ | ||
474 | #define ARGP_HELP_DOC (ARGP_HELP_PRE_DOC | ARGP_HELP_POST_DOC) | ||
475 | #define ARGP_HELP_BUG_ADDR 0x40 /* bug report address */ | ||
476 | #define ARGP_HELP_LONG_ONLY 0x80 /* modify output appropriately to | ||
477 | reflect ARGP_LONG_ONLY mode. */ | ||
478 | |||
479 | /* These ARGP_HELP flags are only understood by argp_state_help. */ | ||
480 | #define ARGP_HELP_EXIT_ERR 0x100 /* Call exit(1) instead of returning. */ | ||
481 | #define ARGP_HELP_EXIT_OK 0x200 /* Call exit(0) instead of returning. */ | ||
482 | |||
483 | /* The standard thing to do after a program command line parsing error, if an | ||
484 | error message has already been printed. */ | ||
485 | #define ARGP_HELP_STD_ERR \ | ||
486 | (ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR) | ||
487 | /* The standard thing to do after a program command line parsing error, if no | ||
488 | more specific error message has been printed. */ | ||
489 | #define ARGP_HELP_STD_USAGE \ | ||
490 | (ARGP_HELP_SHORT_USAGE | ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR) | ||
491 | /* The standard thing to do in response to a --help option. */ | ||
492 | #define ARGP_HELP_STD_HELP \ | ||
493 | (ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG | ARGP_HELP_EXIT_OK \ | ||
494 | | ARGP_HELP_DOC | ARGP_HELP_BUG_ADDR) | ||
495 | |||
496 | /* Output a usage message for ARGP to STREAM. FLAGS are from the set | ||
497 | ARGP_HELP_*. */ | ||
498 | extern void argp_help (const struct argp *__restrict __argp, | ||
499 | FILE *__restrict __stream, | ||
500 | unsigned __flags, char *__restrict __name); | ||
501 | extern void __argp_help (const struct argp *__restrict __argp, | ||
502 | FILE *__restrict __stream, unsigned __flags, | ||
503 | char *__name); | ||
504 | |||
505 | /* The following routines are intended to be called from within an argp | ||
506 | parsing routine (thus taking an argp_state structure as the first | ||
507 | argument). They may or may not print an error message and exit, depending | ||
508 | on the flags in STATE -- in any case, the caller should be prepared for | ||
509 | them *not* to exit, and should return an appropiate error after calling | ||
510 | them. [argp_usage & argp_error should probably be called argp_state_..., | ||
511 | but they're used often enough that they should be short] */ | ||
512 | |||
513 | /* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are | ||
514 | from the set ARGP_HELP_*. */ | ||
515 | extern void argp_state_help (const struct argp_state *__restrict __state, | ||
516 | FILE *__restrict __stream, | ||
517 | unsigned int __flags); | ||
518 | extern void __argp_state_help (const struct argp_state *__restrict __state, | ||
519 | FILE *__restrict __stream, | ||
520 | unsigned int __flags); | ||
521 | |||
522 | /* Possibly output the standard usage message for ARGP to stderr and exit. */ | ||
523 | extern void argp_usage (const struct argp_state *__state); | ||
524 | extern void __argp_usage (const struct argp_state *__state); | ||
525 | |||
526 | /* If appropriate, print the printf string FMT and following args, preceded | ||
527 | by the program name and `:', to stderr, and followed by a `Try ... --help' | ||
528 | message, then exit (1). */ | ||
529 | extern void argp_error (const struct argp_state *__restrict __state, | ||
530 | const char *__restrict __fmt, ...) | ||
531 | __attribute__ ((__format__ (__printf__, 2, 3))); | ||
532 | extern void __argp_error (const struct argp_state *__restrict __state, | ||
533 | const char *__restrict __fmt, ...) | ||
534 | __attribute__ ((__format__ (__printf__, 2, 3))); | ||
535 | |||
536 | /* Similar to the standard gnu error-reporting function error(), but will | ||
537 | respect the ARGP_NO_EXIT and ARGP_NO_ERRS flags in STATE, and will print | ||
538 | to STATE->err_stream. This is useful for argument parsing code that is | ||
539 | shared between program startup (when exiting is desired) and runtime | ||
540 | option parsing (when typically an error code is returned instead). The | ||
541 | difference between this function and argp_error is that the latter is for | ||
542 | *parsing errors*, and the former is for other problems that occur during | ||
543 | parsing but don't reflect a (syntactic) problem with the input. */ | ||
544 | extern void argp_failure (const struct argp_state *__restrict __state, | ||
545 | int __status, int __errnum, | ||
546 | const char *__restrict __fmt, ...) | ||
547 | __attribute__ ((__format__ (__printf__, 4, 5))); | ||
548 | extern void __argp_failure (const struct argp_state *__restrict __state, | ||
549 | int __status, int __errnum, | ||
550 | const char *__restrict __fmt, ...) | ||
551 | __attribute__ ((__format__ (__printf__, 4, 5))); | ||
552 | |||
553 | /* Returns true if the option OPT is a valid short option. */ | ||
554 | extern int _option_is_short (const struct argp_option *__opt) __THROW; | ||
555 | extern int __option_is_short (const struct argp_option *__opt) __THROW; | ||
556 | |||
557 | /* Returns true if the option OPT is in fact the last (unused) entry in an | ||
558 | options array. */ | ||
559 | extern int _option_is_end (const struct argp_option *__opt) __THROW; | ||
560 | extern int __option_is_end (const struct argp_option *__opt) __THROW; | ||
561 | |||
562 | /* Return the input field for ARGP in the parser corresponding to STATE; used | ||
563 | by the help routines. */ | ||
564 | extern void *_argp_input (const struct argp *__restrict __argp, | ||
565 | const struct argp_state *__restrict __state) | ||
566 | __THROW; | ||
567 | extern void *__argp_input (const struct argp *__restrict __argp, | ||
568 | const struct argp_state *__restrict __state) | ||
569 | __THROW; | ||
570 | |||
571 | #ifdef __USE_EXTERN_INLINES | ||
572 | |||
573 | # if !_LIBC | ||
574 | # define __argp_usage argp_usage | ||
575 | # define __argp_state_help argp_state_help | ||
576 | # define __option_is_short _option_is_short | ||
577 | # define __option_is_end _option_is_end | ||
578 | # endif | ||
579 | |||
580 | # ifndef ARGP_EI | ||
581 | # define ARGP_EI extern __inline__ | ||
582 | # endif | ||
583 | |||
584 | ARGP_EI void | ||
585 | __NTH (__argp_usage (const struct argp_state *__state)) | ||
586 | { | ||
587 | __argp_state_help (__state, stderr, ARGP_HELP_STD_USAGE); | ||
588 | } | ||
589 | |||
590 | ARGP_EI int | ||
591 | __NTH (__option_is_short (const struct argp_option *__opt)) | ||
592 | { | ||
593 | if (__opt->flags & OPTION_DOC) | ||
594 | return 0; | ||
595 | else | ||
596 | { | ||
597 | int __key = __opt->key; | ||
598 | return __key > 0 && __key <= UCHAR_MAX && isprint (__key); | ||
599 | } | ||
600 | } | ||
601 | |||
602 | ARGP_EI int | ||
603 | __NTH (__option_is_end (const struct argp_option *__opt)) | ||
604 | { | ||
605 | return !__opt->key && !__opt->name && !__opt->doc && !__opt->group; | ||
606 | } | ||
607 | |||
608 | # if !_LIBC | ||
609 | # undef __argp_usage | ||
610 | # undef __argp_state_help | ||
611 | # undef __option_is_short | ||
612 | # undef __option_is_end | ||
613 | # endif | ||
614 | #endif /* Use extern inlines. */ | ||
615 | |||
616 | #ifdef __cplusplus | ||
617 | } | ||
618 | #endif | ||
619 | |||
620 | #endif /* argp.h */ |
mailbox/asnprintf.c
deleted
100644 → 0
1 | /* Formatted output to strings. | ||
2 | Copyright (C) 1999, 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 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 | #ifdef HAVE_CONFIG_H | ||
19 | # include <config.h> | ||
20 | #endif | ||
21 | |||
22 | /* Specification. */ | ||
23 | #include "vasnprintf.h" | ||
24 | |||
25 | #include <stdarg.h> | ||
26 | |||
27 | char * | ||
28 | asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...) | ||
29 | { | ||
30 | va_list args; | ||
31 | char *result; | ||
32 | |||
33 | va_start (args, format); | ||
34 | result = vasnprintf (resultbuf, lengthp, format, args); | ||
35 | va_end (args); | ||
36 | return result; | ||
37 | } |
mailbox/fnmatch.c
deleted
100644 → 0
1 | /* Copyright (C) 1991,1992,1993,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006 | ||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ | ||
17 | |||
18 | #ifdef HAVE_CONFIG_H | ||
19 | # include <config.h> | ||
20 | #endif | ||
21 | |||
22 | /* Enable GNU extensions in fnmatch.h. */ | ||
23 | #ifndef _GNU_SOURCE | ||
24 | # define _GNU_SOURCE 1 | ||
25 | #endif | ||
26 | |||
27 | #if ! defined __builtin_expect && __GNUC__ < 3 | ||
28 | # define __builtin_expect(expr, expected) (expr) | ||
29 | #endif | ||
30 | |||
31 | #include <fnmatch.h> | ||
32 | |||
33 | #include <alloca.h> | ||
34 | #include <assert.h> | ||
35 | #include <ctype.h> | ||
36 | #include <errno.h> | ||
37 | #include <stddef.h> | ||
38 | #include <stdbool.h> | ||
39 | #include <stdlib.h> | ||
40 | #include <string.h> | ||
41 | |||
42 | #define WIDE_CHAR_SUPPORT \ | ||
43 | (HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_BTOWC \ | ||
44 | && HAVE_WMEMCHR && (HAVE_WMEMCPY || HAVE_WMEMPCPY)) | ||
45 | |||
46 | /* For platform which support the ISO C amendement 1 functionality we | ||
47 | support user defined character classes. */ | ||
48 | #if defined _LIBC || WIDE_CHAR_SUPPORT | ||
49 | /* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */ | ||
50 | # include <wchar.h> | ||
51 | # include <wctype.h> | ||
52 | #endif | ||
53 | |||
54 | /* We need some of the locale data (the collation sequence information) | ||
55 | but there is no interface to get this information in general. Therefore | ||
56 | we support a correct implementation only in glibc. */ | ||
57 | #ifdef _LIBC | ||
58 | # include "../locale/localeinfo.h" | ||
59 | # include "../locale/elem-hash.h" | ||
60 | # include "../locale/coll-lookup.h" | ||
61 | # include <shlib-compat.h> | ||
62 | |||
63 | # define CONCAT(a,b) __CONCAT(a,b) | ||
64 | # define mbsrtowcs __mbsrtowcs | ||
65 | # define fnmatch __fnmatch | ||
66 | extern int fnmatch (const char *pattern, const char *string, int flags); | ||
67 | #endif | ||
68 | |||
69 | #ifndef SIZE_MAX | ||
70 | # define SIZE_MAX ((size_t) -1) | ||
71 | #endif | ||
72 | |||
73 | /* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set. */ | ||
74 | #define NO_LEADING_PERIOD(flags) \ | ||
75 | ((flags & (FNM_FILE_NAME | FNM_PERIOD)) == (FNM_FILE_NAME | FNM_PERIOD)) | ||
76 | |||
77 | /* Comment out all this code if we are using the GNU C Library, and are not | ||
78 | actually compiling the library itself, and have not detected a bug | ||
79 | in the library. This code is part of the GNU C | ||
80 | Library, but also included in many other GNU distributions. Compiling | ||
81 | and linking in this code is a waste when using the GNU C library | ||
82 | (especially if it is a shared library). Rather than having every GNU | ||
83 | program understand `configure --with-gnu-libc' and omit the object files, | ||
84 | it is simpler to just do this in the source for each such file. */ | ||
85 | |||
86 | #if defined _LIBC || !defined __GNU_LIBRARY__ || !HAVE_FNMATCH_GNU | ||
87 | |||
88 | |||
89 | # if ! (defined isblank || HAVE_DECL_ISBLANK) | ||
90 | # define isblank(c) ((c) == ' ' || (c) == '\t') | ||
91 | # endif | ||
92 | |||
93 | # define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) | ||
94 | |||
95 | # if defined _LIBC || WIDE_CHAR_SUPPORT | ||
96 | /* The GNU C library provides support for user-defined character classes | ||
97 | and the functions from ISO C amendement 1. */ | ||
98 | # ifdef CHARCLASS_NAME_MAX | ||
99 | # define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX | ||
100 | # else | ||
101 | /* This shouldn't happen but some implementation might still have this | ||
102 | problem. Use a reasonable default value. */ | ||
103 | # define CHAR_CLASS_MAX_LENGTH 256 | ||
104 | # endif | ||
105 | |||
106 | # ifdef _LIBC | ||
107 | # define IS_CHAR_CLASS(string) __wctype (string) | ||
108 | # else | ||
109 | # define IS_CHAR_CLASS(string) wctype (string) | ||
110 | # endif | ||
111 | |||
112 | # ifdef _LIBC | ||
113 | # define ISWCTYPE(WC, WT) __iswctype (WC, WT) | ||
114 | # else | ||
115 | # define ISWCTYPE(WC, WT) iswctype (WC, WT) | ||
116 | # endif | ||
117 | |||
118 | # if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC | ||
119 | /* In this case we are implementing the multibyte character handling. */ | ||
120 | # define HANDLE_MULTIBYTE 1 | ||
121 | # endif | ||
122 | |||
123 | # else | ||
124 | # define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ | ||
125 | |||
126 | # define IS_CHAR_CLASS(string) \ | ||
127 | (STREQ (string, "alpha") || STREQ (string, "upper") \ | ||
128 | || STREQ (string, "lower") || STREQ (string, "digit") \ | ||
129 | || STREQ (string, "alnum") || STREQ (string, "xdigit") \ | ||
130 | || STREQ (string, "space") || STREQ (string, "print") \ | ||
131 | || STREQ (string, "punct") || STREQ (string, "graph") \ | ||
132 | || STREQ (string, "cntrl") || STREQ (string, "blank")) | ||
133 | # endif | ||
134 | |||
135 | /* Avoid depending on library functions or files | ||
136 | whose names are inconsistent. */ | ||
137 | |||
138 | /* Global variable. */ | ||
139 | static int posixly_correct; | ||
140 | |||
141 | # ifndef internal_function | ||
142 | /* Inside GNU libc we mark some function in a special way. In other | ||
143 | environments simply ignore the marking. */ | ||
144 | # define internal_function | ||
145 | # endif | ||
146 | |||
147 | /* Note that this evaluates C many times. */ | ||
148 | # define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c)) | ||
149 | # define CHAR char | ||
150 | # define UCHAR unsigned char | ||
151 | # define INT int | ||
152 | # define FCT internal_fnmatch | ||
153 | # define EXT ext_match | ||
154 | # define END end_pattern | ||
155 | # define L_(CS) CS | ||
156 | # ifdef _LIBC | ||
157 | # define BTOWC(C) __btowc (C) | ||
158 | # else | ||
159 | # define BTOWC(C) btowc (C) | ||
160 | # endif | ||
161 | # define STRLEN(S) strlen (S) | ||
162 | # define STRCAT(D, S) strcat (D, S) | ||
163 | # ifdef _LIBC | ||
164 | # define MEMPCPY(D, S, N) __mempcpy (D, S, N) | ||
165 | # else | ||
166 | # if HAVE_MEMPCPY | ||
167 | # define MEMPCPY(D, S, N) mempcpy (D, S, N) | ||
168 | # else | ||
169 | # define MEMPCPY(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N))) | ||
170 | # endif | ||
171 | # endif | ||
172 | # define MEMCHR(S, C, N) memchr (S, C, N) | ||
173 | # define STRCOLL(S1, S2) strcoll (S1, S2) | ||
174 | # include "fnmatch_loop.c" | ||
175 | |||
176 | |||
177 | # if HANDLE_MULTIBYTE | ||
178 | # define FOLD(c) ((flags & FNM_CASEFOLD) ? towlower (c) : (c)) | ||
179 | # define CHAR wchar_t | ||
180 | # define UCHAR wint_t | ||
181 | # define INT wint_t | ||
182 | # define FCT internal_fnwmatch | ||
183 | # define EXT ext_wmatch | ||
184 | # define END end_wpattern | ||
185 | # define L_(CS) L##CS | ||
186 | # define BTOWC(C) (C) | ||
187 | # ifdef _LIBC | ||
188 | # define STRLEN(S) __wcslen (S) | ||
189 | # define STRCAT(D, S) __wcscat (D, S) | ||
190 | # define MEMPCPY(D, S, N) __wmempcpy (D, S, N) | ||
191 | # else | ||
192 | # define STRLEN(S) wcslen (S) | ||
193 | # define STRCAT(D, S) wcscat (D, S) | ||
194 | # if HAVE_WMEMPCPY | ||
195 | # define MEMPCPY(D, S, N) wmempcpy (D, S, N) | ||
196 | # else | ||
197 | # define MEMPCPY(D, S, N) (wmemcpy (D, S, N) + (N)) | ||
198 | # endif | ||
199 | # endif | ||
200 | # define MEMCHR(S, C, N) wmemchr (S, C, N) | ||
201 | # define STRCOLL(S1, S2) wcscoll (S1, S2) | ||
202 | # define WIDE_CHAR_VERSION 1 | ||
203 | |||
204 | # undef IS_CHAR_CLASS | ||
205 | /* We have to convert the wide character string in a multibyte string. But | ||
206 | we know that the character class names consist of alphanumeric characters | ||
207 | from the portable character set, and since the wide character encoding | ||
208 | for a member of the portable character set is the same code point as | ||
209 | its single-byte encoding, we can use a simplified method to convert the | ||
210 | string to a multibyte character string. */ | ||
211 | static wctype_t | ||
212 | is_char_class (const wchar_t *wcs) | ||
213 | { | ||
214 | char s[CHAR_CLASS_MAX_LENGTH + 1]; | ||
215 | char *cp = s; | ||
216 | |||
217 | do | ||
218 | { | ||
219 | /* Test for a printable character from the portable character set. */ | ||
220 | # ifdef _LIBC | ||
221 | if (*wcs < 0x20 || *wcs > 0x7e | ||
222 | || *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60) | ||
223 | return (wctype_t) 0; | ||
224 | # else | ||
225 | switch (*wcs) | ||
226 | { | ||
227 | case L' ': case L'!': case L'"': case L'#': case L'%': | ||
228 | case L'&': case L'\'': case L'(': case L')': case L'*': | ||
229 | case L'+': case L',': case L'-': case L'.': case L'/': | ||
230 | case L'0': case L'1': case L'2': case L'3': case L'4': | ||
231 | case L'5': case L'6': case L'7': case L'8': case L'9': | ||
232 | case L':': case L';': case L'<': case L'=': case L'>': | ||
233 | case L'?': | ||
234 | case L'A': case L'B': case L'C': case L'D': case L'E': | ||
235 | case L'F': case L'G': case L'H': case L'I': case L'J': | ||
236 | case L'K': case L'L': case L'M': case L'N': case L'O': | ||
237 | case L'P': case L'Q': case L'R': case L'S': case L'T': | ||
238 | case L'U': case L'V': case L'W': case L'X': case L'Y': | ||
239 | case L'Z': | ||
240 | case L'[': case L'\\': case L']': case L'^': case L'_': | ||
241 | case L'a': case L'b': case L'c': case L'd': case L'e': | ||
242 | case L'f': case L'g': case L'h': case L'i': case L'j': | ||
243 | case L'k': case L'l': case L'm': case L'n': case L'o': | ||
244 | case L'p': case L'q': case L'r': case L's': case L't': | ||
245 | case L'u': case L'v': case L'w': case L'x': case L'y': | ||
246 | case L'z': case L'{': case L'|': case L'}': case L'~': | ||
247 | break; | ||
248 | default: | ||
249 | return (wctype_t) 0; | ||
250 | } | ||
251 | # endif | ||
252 | |||
253 | /* Avoid overrunning the buffer. */ | ||
254 | if (cp == s + CHAR_CLASS_MAX_LENGTH) | ||
255 | return (wctype_t) 0; | ||
256 | |||
257 | *cp++ = (char) *wcs++; | ||
258 | } | ||
259 | while (*wcs != L'\0'); | ||
260 | |||
261 | *cp = '\0'; | ||
262 | |||
263 | # ifdef _LIBC | ||
264 | return __wctype (s); | ||
265 | # else | ||
266 | return wctype (s); | ||
267 | # endif | ||
268 | } | ||
269 | # define IS_CHAR_CLASS(string) is_char_class (string) | ||
270 | |||
271 | # include "fnmatch_loop.c" | ||
272 | # endif | ||
273 | |||
274 | |||
275 | int | ||
276 | fnmatch (const char *pattern, const char *string, int flags) | ||
277 | { | ||
278 | # if HANDLE_MULTIBYTE | ||
279 | # define ALLOCA_LIMIT 2000 | ||
280 | if (__builtin_expect (MB_CUR_MAX, 1) != 1) | ||
281 | { | ||
282 | mbstate_t ps; | ||
283 | size_t patsize; | ||
284 | size_t strsize; | ||
285 | size_t totsize; | ||
286 | wchar_t *wpattern; | ||
287 | wchar_t *wstring; | ||
288 | int res; | ||
289 | |||
290 | /* Calculate the size needed to convert the strings to | ||
291 | wide characters. */ | ||
292 | memset (&ps, '\0', sizeof (ps)); | ||
293 | patsize = mbsrtowcs (NULL, &pattern, 0, &ps) + 1; | ||
294 | if (__builtin_expect (patsize != 0, 1)) | ||
295 | { | ||
296 | assert (mbsinit (&ps)); | ||
297 | strsize = mbsrtowcs (NULL, &string, 0, &ps) + 1; | ||
298 | if (__builtin_expect (strsize != 0, 1)) | ||
299 | { | ||
300 | assert (mbsinit (&ps)); | ||
301 | totsize = patsize + strsize; | ||
302 | if (__builtin_expect (! (patsize <= totsize | ||
303 | && totsize <= SIZE_MAX / sizeof (wchar_t)), | ||
304 | 0)) | ||
305 | { | ||
306 | errno = ENOMEM; | ||
307 | return -1; | ||
308 | } | ||
309 | |||
310 | /* Allocate room for the wide characters. */ | ||
311 | if (__builtin_expect (totsize < ALLOCA_LIMIT, 1)) | ||
312 | wpattern = (wchar_t *) alloca (totsize * sizeof (wchar_t)); | ||
313 | else | ||
314 | { | ||
315 | wpattern = malloc (totsize * sizeof (wchar_t)); | ||
316 | if (__builtin_expect (! wpattern, 0)) | ||
317 | { | ||
318 | errno = ENOMEM; | ||
319 | return -1; | ||
320 | } | ||
321 | } | ||
322 | wstring = wpattern + patsize; | ||
323 | |||
324 | /* Convert the strings into wide characters. */ | ||
325 | mbsrtowcs (wpattern, &pattern, patsize, &ps); | ||
326 | assert (mbsinit (&ps)); | ||
327 | mbsrtowcs (wstring, &string, strsize, &ps); | ||
328 | |||
329 | res = internal_fnwmatch (wpattern, wstring, wstring + strsize - 1, | ||
330 | flags & FNM_PERIOD, flags); | ||
331 | |||
332 | if (__builtin_expect (! (totsize < ALLOCA_LIMIT), 0)) | ||
333 | free (wpattern); | ||
334 | return res; | ||
335 | } | ||
336 | } | ||
337 | } | ||
338 | |||
339 | # endif /* HANDLE_MULTIBYTE */ | ||
340 | |||
341 | return internal_fnmatch (pattern, string, string + strlen (string), | ||
342 | flags & FNM_PERIOD, flags); | ||
343 | } | ||
344 | |||
345 | # ifdef _LIBC | ||
346 | # undef fnmatch | ||
347 | versioned_symbol (libc, __fnmatch, fnmatch, GLIBC_2_2_3); | ||
348 | # if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_3) | ||
349 | strong_alias (__fnmatch, __fnmatch_old) | ||
350 | compat_symbol (libc, __fnmatch_old, fnmatch, GLIBC_2_0); | ||
351 | # endif | ||
352 | libc_hidden_ver (__fnmatch, fnmatch) | ||
353 | # endif | ||
354 | |||
355 | #endif /* _LIBC or not __GNU_LIBRARY__. */ |
mailbox/fnmatch_.h
deleted
100644 → 0
1 | /* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999, 2001, 2002, 2003, | ||
2 | 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 _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 file name 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 */ |
mailbox/fnmatch_loop.c
deleted
100644 → 0
1 | /* Copyright (C) 1991,1992,1993,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006 | ||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ | ||
17 | |||
18 | /* Match STRING against the file name 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 |
mailbox/getdelim.c
deleted
100644 → 0
1 | /* getdelim.c --- Implementation of replacement getdelim function. | ||
2 | Copyright (C) 1994, 1996, 1997, 1998, 2001, 2003, 2005 Free | ||
3 | Software Foundation, Inc. | ||
4 | |||
5 | This program is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU General Public License as | ||
7 | published by the Free Software Foundation; either version 2, or (at | ||
8 | your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | 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 | ||
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
18 | 02110-1301, USA. */ | ||
19 | |||
20 | /* Ported from glibc by Simon Josefsson. */ | ||
21 | |||
22 | #ifdef HAVE_CONFIG_H | ||
23 | # include <config.h> | ||
24 | #endif | ||
25 | |||
26 | #include "getdelim.h" | ||
27 | |||
28 | #include <limits.h> | ||
29 | #include <stdlib.h> | ||
30 | #include <errno.h> | ||
31 | |||
32 | #ifndef SIZE_MAX | ||
33 | # define SIZE_MAX ((size_t) -1) | ||
34 | #endif | ||
35 | #ifndef SSIZE_MAX | ||
36 | # define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) | ||
37 | #endif | ||
38 | #if !HAVE_FLOCKFILE | ||
39 | # undef flockfile | ||
40 | # define flockfile(x) ((void) 0) | ||
41 | #endif | ||
42 | #if !HAVE_FUNLOCKFILE | ||
43 | # undef funlockfile | ||
44 | # define funlockfile(x) ((void) 0) | ||
45 | #endif | ||
46 | |||
47 | /* Read up to (and including) a DELIMITER from FP into *LINEPTR (and | ||
48 | NUL-terminate it). *LINEPTR is a pointer returned from malloc (or | ||
49 | NULL), pointing to *N characters of space. It is realloc'ed as | ||
50 | necessary. Returns the number of characters read (not including | ||
51 | the null terminator), or -1 on error or EOF. */ | ||
52 | |||
53 | ssize_t | ||
54 | getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp) | ||
55 | { | ||
56 | ssize_t result; | ||
57 | size_t cur_len = 0; | ||
58 | |||
59 | if (lineptr == NULL || n == NULL || fp == NULL) | ||
60 | { | ||
61 | errno = EINVAL; | ||
62 | return -1; | ||
63 | } | ||
64 | |||
65 | flockfile (fp); | ||
66 | |||
67 | if (*lineptr == NULL || *n == 0) | ||
68 | { | ||
69 | *n = 120; | ||
70 | *lineptr = (char *) malloc (*n); | ||
71 | if (*lineptr == NULL) | ||
72 | { | ||
73 | result = -1; | ||
74 | goto unlock_return; | ||
75 | } | ||
76 | } | ||
77 | |||
78 | for (;;) | ||
79 | { | ||
80 | int i; | ||
81 | |||
82 | i = getc (fp); | ||
83 | if (i == EOF) | ||
84 | { | ||
85 | result = -1; | ||
86 | break; | ||
87 | } | ||
88 | |||
89 | /* Make enough space for len+1 (for final NUL) bytes. */ | ||
90 | if (cur_len + 1 >= *n) | ||
91 | { | ||
92 | size_t needed_max = | ||
93 | SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX; | ||
94 | size_t needed = 2 * *n + 1; /* Be generous. */ | ||
95 | char *new_lineptr; | ||
96 | |||
97 | if (needed_max < needed) | ||
98 | needed = needed_max; | ||
99 | if (cur_len + 1 >= needed) | ||
100 | { | ||
101 | result = -1; | ||
102 | goto unlock_return; | ||
103 | } | ||
104 | |||
105 | new_lineptr = (char *) realloc (*lineptr, needed); | ||
106 | if (new_lineptr == NULL) | ||
107 | { | ||
108 | result = -1; | ||
109 | goto unlock_return; | ||
110 | } | ||
111 | |||
112 | *lineptr = new_lineptr; | ||
113 | *n = needed; | ||
114 | } | ||
115 | |||
116 | (*lineptr)[cur_len] = i; | ||
117 | cur_len++; | ||
118 | |||
119 | if (i == delimiter) | ||
120 | break; | ||
121 | } | ||
122 | (*lineptr)[cur_len] = '\0'; | ||
123 | result = cur_len ? cur_len : result; | ||
124 | |||
125 | unlock_return: | ||
126 | funlockfile (fp); | ||
127 | return result; | ||
128 | } |
mailbox/getdelim.h
deleted
100644 → 0
1 | /* getdelim.h --- Prototype for replacement getdelim function. | ||
2 | Copyright (C) 2005 Free Software Foundation, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU General Public License as | ||
6 | published by the Free Software Foundation; either version 2, or (at | ||
7 | your option) any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, but | ||
10 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | 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 | ||
16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
17 | 02110-1301, USA. */ | ||
18 | |||
19 | /* Written by Simon Josefsson. */ | ||
20 | |||
21 | /* Get size_t, FILE, ssize_t. And getdelim, if available. */ | ||
22 | # include <stddef.h> | ||
23 | # include <stdio.h> | ||
24 | # include <sys/types.h> | ||
25 | |||
26 | #if !HAVE_DECL_GETDELIM | ||
27 | ssize_t getdelim (char **lineptr, size_t *n, int delimiter, FILE *stream); | ||
28 | #endif /* !HAVE_GETDELIM */ |
mailbox/getline.c
deleted
100644 → 0
1 | /* getline.c --- Implementation of replacement getline function. | ||
2 | Copyright (C) 2005 Free Software Foundation, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU General Public License as | ||
6 | published by the Free Software Foundation; either version 2, or (at | ||
7 | your option) any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, but | ||
10 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | 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 | ||
16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
17 | 02110-1301, USA. */ | ||
18 | |||
19 | /* Written by Simon Josefsson. */ | ||
20 | |||
21 | #ifdef HAVE_CONFIG_H | ||
22 | # include <config.h> | ||
23 | #endif | ||
24 | |||
25 | #include "getdelim.h" | ||
26 | #include "getline.h" | ||
27 | |||
28 | ssize_t | ||
29 | getline (char **lineptr, size_t *n, FILE *stream) | ||
30 | { | ||
31 | return getdelim (lineptr, n, '\n', stream); | ||
32 | } |
mailbox/getline.h
deleted
100644 → 0
1 | /* getline.h --- Prototype for replacement getline function. | ||
2 | Copyright (C) 2005 Free Software Foundation, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU General Public License as | ||
6 | published by the Free Software Foundation; either version 2, or (at | ||
7 | your option) any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, but | ||
10 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | 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 | ||
16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
17 | 02110-1301, USA. */ | ||
18 | |||
19 | /* Written by Simon Josefsson. */ | ||
20 | |||
21 | /* Get size_t, FILE, ssize_t. And getline, if available. */ | ||
22 | # include <stddef.h> | ||
23 | # include <stdio.h> | ||
24 | # include <sys/types.h> | ||
25 | |||
26 | #if !HAVE_DECL_GETLINE | ||
27 | ssize_t getline (char **lineptr, size_t *n, FILE *stream); | ||
28 | #endif /* !HAVE_GETLINE */ |
mailbox/getlogin_r.c
deleted
100644 → 0
1 | /* Provide a working getlogin_r for systems which lack it. | ||
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 and Derek Price */ | ||
20 | |||
21 | #ifdef HAVE_CONFIG_H | ||
22 | # include <config.h> | ||
23 | #endif | ||
24 | |||
25 | #include "getlogin_r.h" | ||
26 | |||
27 | #include <errno.h> | ||
28 | #include <string.h> | ||
29 | #include <unistd.h> | ||
30 | |||
31 | #if !HAVE_DECL_GETLOGIN | ||
32 | char *getlogin (void); | ||
33 | #endif | ||
34 | |||
35 | /* See getlogin_r.h for documentation. */ | ||
36 | int | ||
37 | getlogin_r (char *name, size_t size) | ||
38 | { | ||
39 | char *n; | ||
40 | size_t nlen; | ||
41 | |||
42 | errno = 0; | ||
43 | n = getlogin (); | ||
44 | |||
45 | /* A system function like getlogin_r is never supposed to set errno | ||
46 | to zero, so make sure errno is nonzero here. ENOENT is a | ||
47 | reasonable errno value if getlogin returns NULL. */ | ||
48 | if (!errno) | ||
49 | errno = ENOENT; | ||
50 | |||
51 | if (!n) | ||
52 | return errno; | ||
53 | nlen = strlen (n); | ||
54 | if (size <= nlen) | ||
55 | return ERANGE; | ||
56 | memcpy (name, n, nlen + 1); | ||
57 | return 0; | ||
58 | } |
mailbox/getlogin_r.h
deleted
100644 → 0
1 | /* getlogin_r declaration | ||
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 and Derek Price. */ | ||
20 | |||
21 | #include <stddef.h> | ||
22 | #include <unistd.h> | ||
23 | |||
24 | /* Copies the user's login name to NAME. | ||
25 | The array pointed to by NAME has room for SIZE bytes. | ||
26 | |||
27 | Returns 0 if successful. Upon error, an error number is returned, or -1 in | ||
28 | the case that the login name cannot be found but no specific error is | ||
29 | provided (this case is hopefully rare but is left open by the POSIX spec). | ||
30 | |||
31 | See <http://www.opengroup.org/susv3xsh/getlogin.html>. | ||
32 | */ | ||
33 | #if !HAVE_DECL_GETLOGIN_R | ||
34 | int getlogin_r (char *name, size_t size); | ||
35 | #endif |
mailbox/getndelim2.c
deleted
100644 → 0
1 | /* getndelim2 - Read a line from a stream, stopping at one of 2 delimiters, | ||
2 | with bounded memory allocation. | ||
3 | |||
4 | Copyright (C) 1993, 1996, 1997, 1998, 2000, 2003, 2004 Free Software | ||
5 | Foundation, 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 | ||
18 | License along with this program; if not, write to the Free | ||
19 | Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
20 | Boston, MA 02110-1301 USA. */ | ||
21 | |||
22 | /* Originally written by Jan Brittenson, bson@gnu.ai.mit.edu. */ | ||
23 | |||
24 | #if HAVE_CONFIG_H | ||
25 | # include <config.h> | ||
26 | #endif | ||
27 | |||
28 | #include "getndelim2.h" | ||
29 | |||
30 | #include <stdlib.h> | ||
31 | #include <stddef.h> | ||
32 | |||
33 | #if USE_UNLOCKED_IO | ||
34 | # include "unlocked-io.h" | ||
35 | #endif | ||
36 | |||
37 | #include <limits.h> | ||
38 | #if HAVE_INTTYPES_H | ||
39 | # include <inttypes.h> | ||
40 | #endif | ||
41 | #if HAVE_STDINT_H | ||
42 | # include <stdint.h> | ||
43 | #endif | ||
44 | #ifndef PTRDIFF_MAX | ||
45 | # define PTRDIFF_MAX ((ptrdiff_t) (SIZE_MAX / 2)) | ||
46 | #endif | ||
47 | #ifndef SIZE_MAX | ||
48 | # define SIZE_MAX ((size_t) -1) | ||
49 | #endif | ||
50 | #ifndef SSIZE_MAX | ||
51 | # define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) | ||
52 | #endif | ||
53 | |||
54 | /* The maximum value that getndelim2 can return without suffering from | ||
55 | overflow problems, either internally (because of pointer | ||
56 | subtraction overflow) or due to the API (because of ssize_t). */ | ||
57 | #define GETNDELIM2_MAXIMUM (PTRDIFF_MAX < SSIZE_MAX ? PTRDIFF_MAX : SSIZE_MAX) | ||
58 | |||
59 | /* Try to add at least this many bytes when extending the buffer. | ||
60 | MIN_CHUNK must be no greater than GETNDELIM2_MAXIMUM. */ | ||
61 | #define MIN_CHUNK 64 | ||
62 | |||
63 | ssize_t | ||
64 | getndelim2 (char **lineptr, size_t *linesize, size_t offset, size_t nmax, | ||
65 | int delim1, int delim2, FILE *stream) | ||
66 | { | ||
67 | size_t nbytes_avail; /* Allocated but unused bytes in *LINEPTR. */ | ||
68 | char *read_pos; /* Where we're reading into *LINEPTR. */ | ||
69 | ssize_t bytes_stored = -1; | ||
70 | char *ptr = *lineptr; | ||
71 | size_t size = *linesize; | ||
72 | |||
73 | if (!ptr) | ||
74 | { | ||
75 | size = nmax < MIN_CHUNK ? nmax : MIN_CHUNK; | ||
76 | ptr = malloc (size); | ||
77 | if (!ptr) | ||
78 | return -1; | ||
79 | } | ||
80 | |||
81 | if (size < offset) | ||
82 | goto done; | ||
83 | |||
84 | nbytes_avail = size - offset; | ||
85 | read_pos = ptr + offset; | ||
86 | |||
87 | if (nbytes_avail == 0 && nmax <= size) | ||
88 | goto done; | ||
89 | |||
90 | for (;;) | ||
91 | { | ||
92 | /* Here always ptr + size == read_pos + nbytes_avail. */ | ||
93 | |||
94 | int c; | ||
95 | |||
96 | /* We always want at least one byte left in the buffer, since we | ||
97 | always (unless we get an error while reading the first byte) | ||
98 | NUL-terminate the line buffer. */ | ||
99 | |||
100 | if (nbytes_avail < 2 && size < nmax) | ||
101 | { | ||
102 | size_t newsize = size < MIN_CHUNK ? size + MIN_CHUNK : 2 * size; | ||
103 | char *newptr; | ||
104 | |||
105 | if (! (size < newsize && newsize <= nmax)) | ||
106 | newsize = nmax; | ||
107 | |||
108 | if (GETNDELIM2_MAXIMUM < newsize - offset) | ||
109 | { | ||
110 | size_t newsizemax = offset + GETNDELIM2_MAXIMUM + 1; | ||
111 | if (size == newsizemax) | ||
112 | goto done; | ||
113 | newsize = newsizemax; | ||
114 | } | ||
115 | |||
116 | nbytes_avail = newsize - (read_pos - ptr); | ||
117 | newptr = realloc (ptr, newsize); | ||
118 | if (!newptr) | ||
119 | goto done; | ||
120 | ptr = newptr; | ||
121 | size = newsize; | ||
122 | read_pos = size - nbytes_avail + ptr; | ||
123 | } | ||
124 | |||
125 | c = getc (stream); | ||
126 | if (c == EOF) | ||
127 | { | ||
128 | /* Return partial line, if any. */ | ||
129 | if (read_pos == ptr) | ||
130 | goto done; | ||
131 | else | ||
132 | break; | ||
133 | } | ||
134 | |||
135 | if (nbytes_avail >= 2) | ||
136 | { | ||
137 | *read_pos++ = c; | ||
138 | nbytes_avail--; | ||
139 | } | ||
140 | |||
141 | if (c == delim1 || c == delim2) | ||
142 | /* Return the line. */ | ||
143 | break; | ||
144 | } | ||
145 | |||
146 | /* Done - NUL terminate and return the number of bytes read. | ||
147 | At this point we know that nbytes_avail >= 1. */ | ||
148 | *read_pos = '\0'; | ||
149 | |||
150 | bytes_stored = read_pos - (ptr + offset); | ||
151 | |||
152 | done: | ||
153 | *lineptr = ptr; | ||
154 | *linesize = size; | ||
155 | return bytes_stored; | ||
156 | } |
mailbox/getndelim2.h
deleted
100644 → 0
1 | /* getndelim2 - Read a line from a stream, stopping at one of 2 delimiters, | ||
2 | with bounded memory allocation. | ||
3 | |||
4 | Copyright (C) 2003, 2004 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 | ||
17 | License along with this program; if not, write to the Free | ||
18 | Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
19 | Boston, MA 02110-1301 USA. */ | ||
20 | |||
21 | #ifndef GETNDELIM2_H | ||
22 | #define GETNDELIM2_H 1 | ||
23 | |||
24 | #include <stdio.h> | ||
25 | #include <sys/types.h> | ||
26 | |||
27 | #define GETNLINE_NO_LIMIT ((size_t) -1) | ||
28 | |||
29 | /* Read into a buffer *LINEPTR returned from malloc (or NULL), | ||
30 | pointing to *LINESIZE bytes of space. Store the input bytes | ||
31 | starting at *LINEPTR + OFFSET, and null-terminate them. Reallocate | ||
32 | the buffer as necessary, but if NMAX is not GETNLINE_NO_LIMIT | ||
33 | then do not allocate more than NMAX bytes; if the line is longer | ||
34 | than that, read and discard the extra bytes. Stop reading after | ||
35 | after the first occurrence of DELIM1 or DELIM2, whichever comes | ||
36 | first; a delimiter equal to EOF stands for no delimiter. Read the | ||
37 | input bytes from STREAM. | ||
38 | Return the number of bytes read and stored at *LINEPTR + OFFSET (not | ||
39 | including the NUL terminator), or -1 on error or EOF. */ | ||
40 | extern ssize_t getndelim2 (char **lineptr, size_t *linesize, size_t offset, | ||
41 | size_t nmax, int delim1, int delim2, | ||
42 | FILE *stream); | ||
43 | |||
44 | #endif /* GETNDELIM2_H */ |
mailbox/getopt.c
deleted
100644 → 0
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 | #ifdef HAVE_CONFIG_H | ||
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 | |||
75 | char *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. */ | ||
90 | int optind = 1; | ||
91 | |||
92 | /* Callers store zero here to inhibit the error message | ||
93 | for unrecognized options. */ | ||
94 | |||
95 | int 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 | |||
101 | int optopt = '?'; | ||
102 | |||
103 | /* Keep a global copy of all internal members of getopt_data. */ | ||
104 | |||
105 | static struct _getopt_data getopt_data; | ||
106 | |||
107 | |||
108 | #if defined HAVE_DECL_GETENV && !HAVE_DECL_GETENV | ||
109 | extern 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). */ | ||
116 | extern int __libc_argc; | ||
117 | extern 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 */ | ||
124 | extern 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 | |||
151 | static void | ||
152 | exchange (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 | |||
232 | static 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 | |||
351 | int | ||
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 | |||
1087 | int | ||
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 | ||
1110 | enum { POSIXLY_CORRECT = 0 }; | ||
1111 | #else | ||
1112 | enum { POSIXLY_CORRECT = 1 }; | ||
1113 | #endif | ||
1114 | |||
1115 | int | ||
1116 | getopt (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 | |||
1128 | int | ||
1129 | main (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 */ |
mailbox/getopt.h
deleted
100644 → 0
1 | /* Declarations for getopt. | ||
2 | Copyright (C) 1989-1994,1996-1999,2001,2003,2004,2005 | ||
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 | ||
105 | extern "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 | |||
114 | extern 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 | |||
128 | extern int optind; | ||
129 | |||
130 | /* Callers store zero here to inhibit the error message `getopt' prints | ||
131 | for unrecognized options. */ | ||
132 | |||
133 | extern int opterr; | ||
134 | |||
135 | /* Set to an option character which was unrecognized. */ | ||
136 | |||
137 | extern 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 | |||
161 | struct 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 '\0'. This behavior is specific to the GNU | ||
201 | `getopt'. */ | ||
202 | |||
203 | extern int getopt (int ___argc, char *const *___argv, const char *__shortopts) | ||
204 | __THROW; | ||
205 | |||
206 | #ifndef __need_getopt | ||
207 | extern int getopt_long (int ___argc, char *__getopt_argv_const *___argv, | ||
208 | const char *__shortopts, | ||
209 | const struct option *__longopts, int *__longind) | ||
210 | __THROW; | ||
211 | extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv, | ||
212 | const char *__shortopts, | ||
213 | const struct option *__longopts, int *__longind) | ||
214 | __THROW; | ||
215 | |||
216 | #endif | ||
217 | |||
218 | #ifdef __cplusplus | ||
219 | } | ||
220 | #endif | ||
221 | |||
222 | /* Make sure we later can get all the definitions and declarations. */ | ||
223 | #undef __need_getopt | ||
224 | |||
225 | #endif /* getopt.h */ |
mailbox/getopt1.c
deleted
100644 → 0
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 | ||
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 HAVE_CONFIG_H | ||
21 | # include <config.h> | ||
22 | #endif | ||
23 | |||
24 | #ifdef _LIBC | ||
25 | # include <getopt.h> | ||
26 | #else | ||
27 | # include "getopt.h" | ||
28 | #endif | ||
29 | #include "getopt_int.h" | ||
30 | |||
31 | #include <stdio.h> | ||
32 | |||
33 | /* This needs to come after some library #include | ||
34 | to get __GNU_LIBRARY__ defined. */ | ||
35 | #ifdef __GNU_LIBRARY__ | ||
36 | #include <stdlib.h> | ||
37 | #endif | ||
38 | |||
39 | #ifndef NULL | ||
40 | #define NULL 0 | ||
41 | #endif | ||
42 | |||
43 | int | ||
44 | getopt_long (int argc, char *__getopt_argv_const *argv, const char *options, | ||
45 | const struct option *long_options, int *opt_index) | ||
46 | { | ||
47 | return _getopt_internal (argc, (char **) argv, options, long_options, | ||
48 | opt_index, 0, 0); | ||
49 | } | ||
50 | |||
51 | int | ||
52 | _getopt_long_r (int argc, char **argv, const char *options, | ||
53 | const struct option *long_options, int *opt_index, | ||
54 | struct _getopt_data *d) | ||
55 | { | ||
56 | return _getopt_internal_r (argc, argv, options, long_options, opt_index, | ||
57 | 0, 0, d); | ||
58 | } | ||
59 | |||
60 | /* Like getopt_long, but '-' as well as '--' can indicate a long option. | ||
61 | If an option that starts with '-' (not '--') doesn't match a long option, | ||
62 | but does match a short option, it is parsed as a short option | ||
63 | instead. */ | ||
64 | |||
65 | int | ||
66 | getopt_long_only (int argc, char *__getopt_argv_const *argv, | ||
67 | const char *options, | ||
68 | const struct option *long_options, int *opt_index) | ||
69 | { | ||
70 | return _getopt_internal (argc, (char **) argv, options, long_options, | ||
71 | opt_index, 1, 0); | ||
72 | } | ||
73 | |||
74 | int | ||
75 | _getopt_long_only_r (int argc, char **argv, const char *options, | ||
76 | const struct option *long_options, int *opt_index, | ||
77 | struct _getopt_data *d) | ||
78 | { | ||
79 | return _getopt_internal_r (argc, argv, options, long_options, opt_index, | ||
80 | 1, 0, d); | ||
81 | } | ||
82 | |||
83 | |||
84 | #ifdef TEST | ||
85 | |||
86 | #include <stdio.h> | ||
87 | |||
88 | int | ||
89 | main (int argc, char **argv) | ||
90 | { | ||
91 | int c; | ||
92 | int digit_optind = 0; | ||
93 | |||
94 | while (1) | ||
95 | { | ||
96 | int this_option_optind = optind ? optind : 1; | ||
97 | int option_index = 0; | ||
98 | static struct option long_options[] = | ||
99 | { | ||
100 | {"add", 1, 0, 0}, | ||
101 | {"append", 0, 0, 0}, | ||
102 | {"delete", 1, 0, 0}, | ||
103 | {"verbose", 0, 0, 0}, | ||
104 | {"create", 0, 0, 0}, | ||
105 | {"file", 1, 0, 0}, | ||
106 | {0, 0, 0, 0} | ||
107 | }; | ||
108 | |||
109 | c = getopt_long (argc, argv, "abc:d:0123456789", | ||
110 | long_options, &option_index); | ||
111 | if (c == -1) | ||
112 | break; | ||
113 | |||
114 | switch (c) | ||
115 | { | ||
116 | case 0: | ||
117 | printf ("option %s", long_options[option_index].name); | ||
118 | if (optarg) | ||
119 | printf (" with arg %s", optarg); | ||
120 | printf ("\n"); | ||
121 | break; | ||
122 | |||
123 | case '0': | ||
124 | case '1': | ||
125 | case '2': | ||
126 | case '3': | ||
127 | case '4': | ||
128 | case '5': | ||
129 | case '6': | ||
130 | case '7': | ||
131 | case '8': | ||
132 | case '9': | ||
133 | if (digit_optind != 0 && digit_optind != this_option_optind) | ||
134 | printf ("digits occur in two different argv-elements.\n"); | ||
135 | digit_optind = this_option_optind; | ||
136 | printf ("option %c\n", c); | ||
137 | break; | ||
138 | |||
139 | case 'a': | ||
140 | printf ("option a\n"); | ||
141 | break; | ||
142 | |||
143 | case 'b': | ||
144 | printf ("option b\n"); | ||
145 | break; | ||
146 | |||
147 | case 'c': | ||
148 | printf ("option c with value `%s'\n", optarg); | ||
149 | break; | ||
150 | |||
151 | case 'd': | ||
152 | printf ("option d with value `%s'\n", optarg); | ||
153 | break; | ||
154 | |||
155 | case '?': | ||
156 | break; | ||
157 | |||
158 | default: | ||
159 | printf ("?? getopt returned character code 0%o ??\n", c); | ||
160 | } | ||
161 | } | ||
162 | |||
163 | if (optind < argc) | ||
164 | { | ||
165 | printf ("non-option ARGV-elements: "); | ||
166 | while (optind < argc) | ||
167 | printf ("%s ", argv[optind++]); | ||
168 | printf ("\n"); | ||
169 | } | ||
170 | |||
171 | exit (0); | ||
172 | } | ||
173 | |||
174 | #endif /* TEST */ |
mailbox/getopt_.h
deleted
100644 → 0
1 | /* Declarations for getopt. | ||
2 | Copyright (C) 1989-1994,1996-1999,2001,2003,2004,2005 | ||
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 | ||
105 | extern "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 | |||
114 | extern 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 | |||
128 | extern int optind; | ||
129 | |||
130 | /* Callers store zero here to inhibit the error message `getopt' prints | ||
131 | for unrecognized options. */ | ||
132 | |||
133 | extern int opterr; | ||
134 | |||
135 | /* Set to an option character which was unrecognized. */ | ||
136 | |||
137 | extern 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 | |||
161 | struct 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 '\0'. This behavior is specific to the GNU | ||
201 | `getopt'. */ | ||
202 | |||
203 | extern int getopt (int ___argc, char *const *___argv, const char *__shortopts) | ||
204 | __THROW; | ||
205 | |||
206 | #ifndef __need_getopt | ||
207 | extern int getopt_long (int ___argc, char *__getopt_argv_const *___argv, | ||
208 | const char *__shortopts, | ||
209 | const struct option *__longopts, int *__longind) | ||
210 | __THROW; | ||
211 | extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv, | ||
212 | const char *__shortopts, | ||
213 | const struct option *__longopts, int *__longind) | ||
214 | __THROW; | ||
215 | |||
216 | #endif | ||
217 | |||
218 | #ifdef __cplusplus | ||
219 | } | ||
220 | #endif | ||
221 | |||
222 | /* Make sure we later can get all the definitions and declarations. */ | ||
223 | #undef __need_getopt | ||
224 | |||
225 | #endif /* getopt.h */ |
mailbox/getopt_int.h
deleted
100644 → 0
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 | |||
23 | extern 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. */ | ||
33 | struct _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 | |||
114 | extern 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 | |||
120 | extern 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 | |||
125 | extern 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 */ |
mailbox/gettext.h
deleted
100644 → 0
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 | #else | ||
28 | |||
29 | /* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which | ||
30 | chokes if dcgettext is defined as a macro. So include it now, to make | ||
31 | later inclusions of <locale.h> a NOP. We don't include <libintl.h> | ||
32 | as well because people using "gettext.h" will not include <libintl.h>, | ||
33 | and also including <libintl.h> would fail on SunOS 4, whereas <locale.h> | ||
34 | is OK. */ | ||
35 | #if defined(__sun) | ||
36 | # include <locale.h> | ||
37 | #endif | ||
38 | |||
39 | /* Many header files from the libstdc++ coming with g++ 3.3 or newer include | ||
40 | <libintl.h>, which chokes if dcgettext is defined as a macro. So include | ||
41 | it now, to make later inclusions of <libintl.h> a NOP. */ | ||
42 | #if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3) | ||
43 | # include <cstdlib> | ||
44 | # if (__GLIBC__ >= 2) || _GLIBCXX_HAVE_LIBINTL_H | ||
45 | # include <libintl.h> | ||
46 | # endif | ||
47 | #endif | ||
48 | |||
49 | /* Disabled NLS. | ||
50 | The casts to 'const char *' serve the purpose of producing warnings | ||
51 | for invalid uses of the value returned from these functions. | ||
52 | On pre-ANSI systems without 'const', the config.h file is supposed to | ||
53 | contain "#define const". */ | ||
54 | # define gettext(Msgid) ((const char *) (Msgid)) | ||
55 | # define dgettext(Domainname, Msgid) ((const char *) (Msgid)) | ||
56 | # define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid)) | ||
57 | # define ngettext(Msgid1, Msgid2, N) \ | ||
58 | ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) | ||
59 | # define dngettext(Domainname, Msgid1, Msgid2, N) \ | ||
60 | ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) | ||
61 | # define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ | ||
62 | ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) | ||
63 | # define textdomain(Domainname) ((const char *) (Domainname)) | ||
64 | # define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname)) | ||
65 | # define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset)) | ||
66 | |||
67 | #endif | ||
68 | |||
69 | /* A pseudo function call that serves as a marker for the automated | ||
70 | extraction of messages, but does not call gettext(). The run-time | ||
71 | translation is done at a different place in the code. | ||
72 | The argument, String, should be a literal string. Concatenated strings | ||
73 | and other string expressions won't work. | ||
74 | The macro's expansion is not parenthesized, so that it is suitable as | ||
75 | initializer for static 'char[]' or 'const char[]' variables. */ | ||
76 | #define gettext_noop(String) String | ||
77 | |||
78 | /* The separator between msgctxt and msgid in a .mo file. */ | ||
79 | #define GETTEXT_CONTEXT_GLUE "\004" | ||
80 | |||
81 | /* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a | ||
82 | MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be | ||
83 | short and rarely need to change. | ||
84 | The letter 'p' stands for 'particular' or 'special'. */ | ||
85 | #define pgettext(Msgctxt, Msgid) \ | ||
86 | pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) | ||
87 | #define dpgettext(Domainname, Msgctxt, Msgid) \ | ||
88 | pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) | ||
89 | #define dcpgettext(Domainname, Msgctxt, Msgid, Category) \ | ||
90 | pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category) | ||
91 | #define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ | ||
92 | npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) | ||
93 | #define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ | ||
94 | npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) | ||
95 | #define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \ | ||
96 | npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category) | ||
97 | |||
98 | #ifdef __GNUC__ | ||
99 | __inline | ||
100 | #else | ||
101 | #ifdef __cplusplus | ||
102 | inline | ||
103 | #endif | ||
104 | #endif | ||
105 | static const char * | ||
106 | pgettext_aux (const char *domain, | ||
107 | const char *msg_ctxt_id, const char *msgid, | ||
108 | int category) | ||
109 | { | ||
110 | const char *translation = dcgettext (domain, msg_ctxt_id, category); | ||
111 | if (translation == msg_ctxt_id) | ||
112 | return msgid; | ||
113 | else | ||
114 | return translation; | ||
115 | } | ||
116 | |||
117 | #ifdef __GNUC__ | ||
118 | __inline | ||
119 | #else | ||
120 | #ifdef __cplusplus | ||
121 | inline | ||
122 | #endif | ||
123 | #endif | ||
124 | static const char * | ||
125 | npgettext_aux (const char *domain, | ||
126 | const char *msg_ctxt_id, const char *msgid, | ||
127 | const char *msgid_plural, unsigned long int n, | ||
128 | int category) | ||
129 | { | ||
130 | const char *translation = | ||
131 | dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); | ||
132 | if (translation == msg_ctxt_id || translation == msgid_plural) | ||
133 | return (n == 1 ? msgid : msgid_plural); | ||
134 | else | ||
135 | return translation; | ||
136 | } | ||
137 | |||
138 | /* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID | ||
139 | can be arbitrary expressions. But for string literals these macros are | ||
140 | less efficient than those above. */ | ||
141 | |||
142 | #include <string.h> | ||
143 | |||
144 | #define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \ | ||
145 | (__GNUC__ >= 3 || defined __cplusplus) | ||
146 | |||
147 | #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS | ||
148 | #include <stdlib.h> | ||
149 | #endif | ||
150 | |||
151 | #define pgettext_expr(Msgctxt, Msgid) \ | ||
152 | dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES) | ||
153 | #define dpgettext_expr(Domainname, Msgctxt, Msgid) \ | ||
154 | dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES) | ||
155 | |||
156 | #ifdef __GNUC__ | ||
157 | __inline | ||
158 | #else | ||
159 | #ifdef __cplusplus | ||
160 | inline | ||
161 | #endif | ||
162 | #endif | ||
163 | static const char * | ||
164 | dcpgettext_expr (const char *domain, | ||
165 | const char *msgctxt, const char *msgid, | ||
166 | int category) | ||
167 | { | ||
168 | size_t msgctxt_len = strlen (msgctxt) + 1; | ||
169 | size_t msgid_len = strlen (msgid) + 1; | ||
170 | const char *translation; | ||
171 | #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS | ||
172 | char msg_ctxt_id[msgctxt_len + msgid_len]; | ||
173 | #else | ||
174 | char buf[1024]; | ||
175 | char *msg_ctxt_id = | ||
176 | (msgctxt_len + msgid_len <= sizeof (buf) | ||
177 | ? buf | ||
178 | : (char *) malloc (msgctxt_len + msgid_len)); | ||
179 | if (msg_ctxt_id != NULL) | ||
180 | #endif | ||
181 | { | ||
182 | memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); | ||
183 | msg_ctxt_id[msgctxt_len - 1] = '\004'; | ||
184 | memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); | ||
185 | translation = dcgettext (domain, msg_ctxt_id, category); | ||
186 | #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS | ||
187 | if (msg_ctxt_id != buf) | ||
188 | free (msg_ctxt_id); | ||
189 | #endif | ||
190 | if (translation != msg_ctxt_id) | ||
191 | return translation; | ||
192 | } | ||
193 | return msgid; | ||
194 | } | ||
195 | |||
196 | #define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \ | ||
197 | dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) | ||
198 | #define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ | ||
199 | dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) | ||
200 | |||
201 | #ifdef __GNUC__ | ||
202 | __inline | ||
203 | #else | ||
204 | #ifdef __cplusplus | ||
205 | inline | ||
206 | #endif | ||
207 | #endif | ||
208 | static const char * | ||
209 | dcnpgettext_expr (const char *domain, | ||
210 | const char *msgctxt, const char *msgid, | ||
211 | const char *msgid_plural, unsigned long int n, | ||
212 | int category) | ||
213 | { | ||
214 | size_t msgctxt_len = strlen (msgctxt) + 1; | ||
215 | size_t msgid_len = strlen (msgid) + 1; | ||
216 | const char *translation; | ||
217 | #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS | ||
218 | char msg_ctxt_id[msgctxt_len + msgid_len]; | ||
219 | #else | ||
220 | char buf[1024]; | ||
221 | char *msg_ctxt_id = | ||
222 | (msgctxt_len + msgid_len <= sizeof (buf) | ||
223 | ? buf | ||
224 | : (char *) malloc (msgctxt_len + msgid_len)); | ||
225 | if (msg_ctxt_id != NULL) | ||
226 | #endif | ||
227 | { | ||
228 | memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); | ||
229 | msg_ctxt_id[msgctxt_len - 1] = '\004'; | ||
230 | memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); | ||
231 | translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); | ||
232 | #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS | ||
233 | if (msg_ctxt_id != buf) | ||
234 | free (msg_ctxt_id); | ||
235 | #endif | ||
236 | if (!(translation == msg_ctxt_id || translation == msgid_plural)) | ||
237 | return translation; | ||
238 | } | ||
239 | return (n == 1 ? msgid : msgid_plural); | ||
240 | } | ||
241 | |||
242 | #endif /* _LIBGETTEXT_H */ |
mailbox/glob-libc.h
deleted
100644 → 0
1 | /* Copyright (C) 1991,92,95-98,2000,2001,2004-2006 Free Software Foundation, Inc. | ||
2 | This file is part of the GNU C Library. | ||
3 | |||
4 | The GNU C Library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Lesser General Public | ||
6 | License as published by the Free Software Foundation; either | ||
7 | version 2.1 of the License, or (at your option) any later version. | ||
8 | |||
9 | The GNU C Library 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 GNU | ||
12 | Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General Public | ||
15 | License along with the GNU C Library; if not, write to the Free | ||
16 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
17 | 02111-1307 USA. */ | ||
18 | |||
19 | #ifndef _GLOB_H | ||
20 | #define _GLOB_H 1 | ||
21 | |||
22 | #ifndef __GLOB_GNULIB | ||
23 | # include <sys/cdefs.h> | ||
24 | #endif | ||
25 | |||
26 | __BEGIN_DECLS | ||
27 | |||
28 | /* We need `size_t' for the following definitions. */ | ||
29 | #ifndef __size_t | ||
30 | # if defined __GNUC__ && __GNUC__ >= 2 | ||
31 | typedef __SIZE_TYPE__ __size_t; | ||
32 | # ifdef __USE_XOPEN | ||
33 | typedef __SIZE_TYPE__ size_t; | ||
34 | # endif | ||
35 | # else | ||
36 | # include <stddef.h> | ||
37 | # ifndef __size_t | ||
38 | # define __size_t size_t | ||
39 | # endif | ||
40 | # endif | ||
41 | #else | ||
42 | /* The GNU CC stddef.h version defines __size_t as empty. We need a real | ||
43 | definition. */ | ||
44 | # undef __size_t | ||
45 | # define __size_t size_t | ||
46 | #endif | ||
47 | |||
48 | /* Bits set in the FLAGS argument to `glob'. */ | ||
49 | #define GLOB_ERR (1 << 0)/* Return on read errors. */ | ||
50 | #define GLOB_MARK (1 << 1)/* Append a slash to each name. */ | ||
51 | #define GLOB_NOSORT (1 << 2)/* Don't sort the names. */ | ||
52 | #define GLOB_DOOFFS (1 << 3)/* Insert PGLOB->gl_offs NULLs. */ | ||
53 | #define GLOB_NOCHECK (1 << 4)/* If nothing matches, return the pattern. */ | ||
54 | #define GLOB_APPEND (1 << 5)/* Append to results of a previous call. */ | ||
55 | #define GLOB_NOESCAPE (1 << 6)/* Backslashes don't quote metacharacters. */ | ||
56 | #define GLOB_PERIOD (1 << 7)/* Leading `.' can be matched by metachars. */ | ||
57 | |||
58 | #if !defined __USE_POSIX2 || defined __USE_BSD || defined __USE_GNU | ||
59 | # define GLOB_MAGCHAR (1 << 8)/* Set in gl_flags if any metachars seen. */ | ||
60 | # define GLOB_ALTDIRFUNC (1 << 9)/* Use gl_opendir et al functions. */ | ||
61 | # define GLOB_BRACE (1 << 10)/* Expand "{a,b}" to "a" "b". */ | ||
62 | # define GLOB_NOMAGIC (1 << 11)/* If no magic chars, return the pattern. */ | ||
63 | # define GLOB_TILDE (1 << 12)/* Expand ~user and ~ to home directories. */ | ||
64 | # define GLOB_ONLYDIR (1 << 13)/* Match only directories. */ | ||
65 | # define GLOB_TILDE_CHECK (1 << 14)/* Like GLOB_TILDE but return an error | ||
66 | if the user name is not available. */ | ||
67 | # define __GLOB_FLAGS (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \ | ||
68 | GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND| \ | ||
69 | GLOB_PERIOD|GLOB_ALTDIRFUNC|GLOB_BRACE| \ | ||
70 | GLOB_NOMAGIC|GLOB_TILDE|GLOB_ONLYDIR|GLOB_TILDE_CHECK) | ||
71 | #else | ||
72 | # define __GLOB_FLAGS (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \ | ||
73 | GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND| \ | ||
74 | GLOB_PERIOD) | ||
75 | #endif | ||
76 | |||
77 | /* Error returns from `glob'. */ | ||
78 | #define GLOB_NOSPACE 1 /* Ran out of memory. */ | ||
79 | #define GLOB_ABORTED 2 /* Read error. */ | ||
80 | #define GLOB_NOMATCH 3 /* No matches found. */ | ||
81 | #define GLOB_NOSYS 4 /* Not implemented. */ | ||
82 | #ifdef __USE_GNU | ||
83 | /* Previous versions of this file defined GLOB_ABEND instead of | ||
84 | GLOB_ABORTED. Provide a compatibility definition here. */ | ||
85 | # define GLOB_ABEND GLOB_ABORTED | ||
86 | #endif | ||
87 | |||
88 | /* Structure describing a globbing run. */ | ||
89 | #ifdef __USE_GNU | ||
90 | struct stat; | ||
91 | #endif | ||
92 | typedef struct | ||
93 | { | ||
94 | __size_t gl_pathc; /* Count of paths matched by the pattern. */ | ||
95 | char **gl_pathv; /* List of matched pathnames. */ | ||
96 | __size_t gl_offs; /* Slots to reserve in `gl_pathv'. */ | ||
97 | int gl_flags; /* Set to FLAGS, maybe | GLOB_MAGCHAR. */ | ||
98 | |||
99 | /* If the GLOB_ALTDIRFUNC flag is set, the following functions | ||
100 | are used instead of the normal file access functions. */ | ||
101 | void (*gl_closedir) (void *); | ||
102 | #ifdef __USE_GNU | ||
103 | struct dirent *(*gl_readdir) (void *); | ||
104 | #else | ||
105 | void *(*gl_readdir) (void *); | ||
106 | #endif | ||
107 | void *(*gl_opendir) (const char *); | ||
108 | #ifdef __USE_GNU | ||
109 | int (*gl_lstat) (const char *__restrict, struct stat *__restrict); | ||
110 | int (*gl_stat) (const char *__restrict, struct stat *__restrict); | ||
111 | #else | ||
112 | int (*gl_lstat) (const char *__restrict, void *__restrict); | ||
113 | int (*gl_stat) (const char *__restrict, void *__restrict); | ||
114 | #endif | ||
115 | } glob_t; | ||
116 | |||
117 | #if defined __USE_LARGEFILE64 && !defined __GLOB_GNULIB | ||
118 | # ifdef __USE_GNU | ||
119 | struct stat64; | ||
120 | # endif | ||
121 | typedef struct | ||
122 | { | ||
123 | __size_t gl_pathc; | ||
124 | char **gl_pathv; | ||
125 | __size_t gl_offs; | ||
126 | int gl_flags; | ||
127 | |||
128 | /* If the GLOB_ALTDIRFUNC flag is set, the following functions | ||
129 | are used instead of the normal file access functions. */ | ||
130 | void (*gl_closedir) (void *); | ||
131 | # ifdef __USE_GNU | ||
132 | struct dirent64 *(*gl_readdir) (void *); | ||
133 | # else | ||
134 | void *(*gl_readdir) (void *); | ||
135 | # endif | ||
136 | void *(*gl_opendir) (const char *); | ||
137 | # ifdef __USE_GNU | ||
138 | int (*gl_lstat) (const char *__restrict, struct stat64 *__restrict); | ||
139 | int (*gl_stat) (const char *__restrict, struct stat64 *__restrict); | ||
140 | # else | ||
141 | int (*gl_lstat) (const char *__restrict, void *__restrict); | ||
142 | int (*gl_stat) (const char *__restrict, void *__restrict); | ||
143 | # endif | ||
144 | } glob64_t; | ||
145 | #endif | ||
146 | |||
147 | #if __USE_FILE_OFFSET64 && __GNUC__ < 2 && !defined __GLOB_GNULIB | ||
148 | # define glob glob64 | ||
149 | # define globfree globfree64 | ||
150 | #endif | ||
151 | |||
152 | /* Do glob searching for PATTERN, placing results in PGLOB. | ||
153 | The bits defined above may be set in FLAGS. | ||
154 | If a directory cannot be opened or read and ERRFUNC is not nil, | ||
155 | it is called with the pathname that caused the error, and the | ||
156 | `errno' value from the failing call; if it returns non-zero | ||
157 | `glob' returns GLOB_ABEND; if it returns zero, the error is ignored. | ||
158 | If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned. | ||
159 | Otherwise, `glob' returns zero. */ | ||
160 | #if !defined __USE_FILE_OFFSET64 || __GNUC__ < 2 || defined __GLOB_GNULIB | ||
161 | extern int glob (const char *__restrict __pattern, int __flags, | ||
162 | int (*__errfunc) (const char *, int), | ||
163 | glob_t *__restrict __pglob) __THROW; | ||
164 | |||
165 | /* Free storage allocated in PGLOB by a previous `glob' call. */ | ||
166 | extern void globfree (glob_t *__pglob) __THROW; | ||
167 | #else | ||
168 | extern int __REDIRECT_NTH (glob, (const char *__restrict __pattern, | ||
169 | int __flags, | ||
170 | int (*__errfunc) (const char *, int), | ||
171 | glob_t *__restrict __pglob), glob64); | ||
172 | |||
173 | extern void __REDIRECT_NTH (globfree, (glob_t *__pglob), globfree64); | ||
174 | #endif | ||
175 | |||
176 | #if defined __USE_LARGEFILE64 && !defined __GLOB_GNULIB | ||
177 | extern int glob64 (const char *__restrict __pattern, int __flags, | ||
178 | int (*__errfunc) (const char *, int), | ||
179 | glob64_t *__restrict __pglob) __THROW; | ||
180 | |||
181 | extern void globfree64 (glob64_t *__pglob) __THROW; | ||
182 | #endif | ||
183 | |||
184 | |||
185 | #ifdef __USE_GNU | ||
186 | /* Return nonzero if PATTERN contains any metacharacters. | ||
187 | Metacharacters can be quoted with backslashes if QUOTE is nonzero. | ||
188 | |||
189 | This function is not part of the interface specified by POSIX.2 | ||
190 | but several programs want to use it. */ | ||
191 | extern int glob_pattern_p (const char *__pattern, int __quote) __THROW; | ||
192 | #endif | ||
193 | |||
194 | __END_DECLS | ||
195 | |||
196 | #endif /* glob.h */ |
mailbox/glob.c
deleted
100644 → 0
1 | /* Copyright (C) 1991-2002,2003,2004,2005,2006 Free Software Foundation, Inc. | ||
2 | This file is part of the GNU C Library. | ||
3 | |||
4 | The GNU C Library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Lesser General Public | ||
6 | License as published by the Free Software Foundation; either | ||
7 | version 2.1 of the License, or (at your option) any later version. | ||
8 | |||
9 | The GNU C Library 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 GNU | ||
12 | Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General Public | ||
15 | License along with the GNU C Library; if not, write to the Free | ||
16 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
17 | 02111-1307 USA. */ | ||
18 | |||
19 | #ifdef HAVE_CONFIG_H | ||
20 | # include <config.h> | ||
21 | #endif | ||
22 | |||
23 | #include <glob.h> | ||
24 | |||
25 | #include <errno.h> | ||
26 | #include <sys/types.h> | ||
27 | #include <sys/stat.h> | ||
28 | #include <stddef.h> | ||
29 | |||
30 | /* Outcomment the following line for production quality code. */ | ||
31 | /* #define NDEBUG 1 */ | ||
32 | #include <assert.h> | ||
33 | |||
34 | #include <stdio.h> /* Needed on stupid SunOS for assert. */ | ||
35 | |||
36 | #if !defined _LIBC || !defined GLOB_ONLY_P | ||
37 | |||
38 | #include <unistd.h> | ||
39 | #if !defined POSIX && defined _POSIX_VERSION | ||
40 | # define POSIX | ||
41 | #endif | ||
42 | |||
43 | #include <pwd.h> | ||
44 | |||
45 | #include <errno.h> | ||
46 | #ifndef __set_errno | ||
47 | # define __set_errno(val) errno = (val) | ||
48 | #endif | ||
49 | |||
50 | #include <dirent.h> | ||
51 | |||
52 | |||
53 | /* In GNU systems, <dirent.h> defines this macro for us. */ | ||
54 | #ifndef _D_EXACT_NAMLEN | ||
55 | # define _D_EXACT_NAMLEN(dirent) strlen ((dirent)->d_name) | ||
56 | #endif | ||
57 | |||
58 | /* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available | ||
59 | if the `d_type' member for `struct dirent' is available. | ||
60 | HAVE_STRUCT_DIRENT_D_TYPE plays the same role in GNULIB. */ | ||
61 | #if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE | ||
62 | /* True if the directory entry D must be of type T. */ | ||
63 | # define DIRENT_MUST_BE(d, t) ((d)->d_type == (t)) | ||
64 | |||
65 | /* True if the directory entry D might be a symbolic link. */ | ||
66 | # define DIRENT_MIGHT_BE_SYMLINK(d) \ | ||
67 | ((d)->d_type == DT_UNKNOWN || (d)->d_type == DT_LNK) | ||
68 | |||
69 | /* True if the directory entry D might be a directory. */ | ||
70 | # define DIRENT_MIGHT_BE_DIR(d) \ | ||
71 | ((d)->d_type == DT_DIR || DIRENT_MIGHT_BE_SYMLINK (d)) | ||
72 | |||
73 | #else /* !HAVE_D_TYPE */ | ||
74 | # define DIRENT_MUST_BE(d, t) false | ||
75 | # define DIRENT_MIGHT_BE_SYMLINK(d) true | ||
76 | # define DIRENT_MIGHT_BE_DIR(d) true | ||
77 | #endif /* HAVE_D_TYPE */ | ||
78 | |||
79 | /* If the system has the `struct dirent64' type we use it internally. */ | ||
80 | #if defined _LIBC && !defined COMPILE_GLOB64 | ||
81 | # if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__ | ||
82 | # define CONVERT_D_INO(d64, d32) | ||
83 | # else | ||
84 | # define CONVERT_D_INO(d64, d32) \ | ||
85 | (d64)->d_ino = (d32)->d_ino; | ||
86 | # endif | ||
87 | |||
88 | # ifdef _DIRENT_HAVE_D_TYPE | ||
89 | # define CONVERT_D_TYPE(d64, d32) \ | ||
90 | (d64)->d_type = (d32)->d_type; | ||
91 | # else | ||
92 | # define CONVERT_D_TYPE(d64, d32) | ||
93 | # endif | ||
94 | |||
95 | # define CONVERT_DIRENT_DIRENT64(d64, d32) \ | ||
96 | memcpy ((d64)->d_name, (d32)->d_name, _D_EXACT_NAMLEN (d32) + 1); \ | ||
97 | CONVERT_D_INO (d64, d32) \ | ||
98 | CONVERT_D_TYPE (d64, d32) | ||
99 | #endif | ||
100 | |||
101 | |||
102 | #if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__ | ||
103 | /* Posix does not require that the d_ino field be present, and some | ||
104 | systems do not provide it. */ | ||
105 | # define REAL_DIR_ENTRY(dp) 1 | ||
106 | #else | ||
107 | # define REAL_DIR_ENTRY(dp) (dp->d_ino != 0) | ||
108 | #endif /* POSIX */ | ||
109 | |||
110 | #include <stdlib.h> | ||
111 | #include <string.h> | ||
112 | |||
113 | /* NAME_MAX is usually defined in <dirent.h> or <limits.h>. */ | ||
114 | #include <limits.h> | ||
115 | #ifndef NAME_MAX | ||
116 | # define NAME_MAX (sizeof (((struct dirent *) 0)->d_name)) | ||
117 | #endif | ||
118 | |||
119 | #include <alloca.h> | ||
120 | |||
121 | #ifdef _LIBC | ||
122 | # undef strdup | ||
123 | # define strdup(str) __strdup (str) | ||
124 | # define sysconf(id) __sysconf (id) | ||
125 | # define closedir(dir) __closedir (dir) | ||
126 | # define opendir(name) __opendir (name) | ||
127 | # define readdir(str) __readdir64 (str) | ||
128 | # define getpwnam_r(name, bufp, buf, len, res) \ | ||
129 | __getpwnam_r (name, bufp, buf, len, res) | ||
130 | # ifndef __stat64 | ||
131 | # define __stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf) | ||
132 | # endif | ||
133 | # define struct_stat64 struct stat64 | ||
134 | #else /* !_LIBC */ | ||
135 | # include "getlogin_r.h" | ||
136 | # include "mempcpy.h" | ||
137 | # include "stat-macros.h" | ||
138 | # include "strdup.h" | ||
139 | # define __stat64(fname, buf) stat (fname, buf) | ||
140 | # define struct_stat64 struct stat | ||
141 | # define __stat(fname, buf) stat (fname, buf) | ||
142 | # define __alloca alloca | ||
143 | # define __readdir readdir | ||
144 | # define __readdir64 readdir64 | ||
145 | # define __glob_pattern_p glob_pattern_p | ||
146 | #endif /* _LIBC */ | ||
147 | |||
148 | #include <stdbool.h> | ||
149 | #include <fnmatch.h> | ||
150 | |||
151 | #ifdef _SC_GETPW_R_SIZE_MAX | ||
152 | # define GETPW_R_SIZE_MAX() sysconf (_SC_GETPW_R_SIZE_MAX) | ||
153 | #else | ||
154 | # define GETPW_R_SIZE_MAX() (-1) | ||
155 | #endif | ||
156 | #ifdef _SC_LOGIN_NAME_MAX | ||
157 | # define GET_LOGIN_NAME_MAX() sysconf (_SC_LOGIN_NAME_MAX) | ||
158 | #else | ||
159 | # define GET_LOGIN_NAME_MAX() (-1) | ||
160 | #endif | ||
161 | |||
162 | static const char *next_brace_sub (const char *begin, int flags) __THROW; | ||
163 | |||
164 | #endif /* !defined _LIBC || !defined GLOB_ONLY_P */ | ||
165 | |||
166 | static int glob_in_dir (const char *pattern, const char *directory, | ||
167 | int flags, int (*errfunc) (const char *, int), | ||
168 | glob_t *pglob); | ||
169 | |||
170 | #if !defined _LIBC || !defined GLOB_ONLY_P | ||
171 | static int prefix_array (const char *prefix, char **array, size_t n) __THROW; | ||
172 | static int collated_compare (const void *, const void *) __THROW; | ||
173 | |||
174 | |||
175 | /* Find the end of the sub-pattern in a brace expression. */ | ||
176 | static const char * | ||
177 | next_brace_sub (const char *cp, int flags) | ||
178 | { | ||
179 | unsigned int depth = 0; | ||
180 | while (*cp != '\0') | ||
181 | if ((flags & GLOB_NOESCAPE) == 0 && *cp == '\\') | ||
182 | { | ||
183 | if (*++cp == '\0') | ||
184 | break; | ||
185 | ++cp; | ||
186 | } | ||
187 | else | ||
188 | { | ||
189 | if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0)) | ||
190 | break; | ||
191 | |||
192 | if (*cp++ == '{') | ||
193 | depth++; | ||
194 | } | ||
195 | |||
196 | return *cp != '\0' ? cp : NULL; | ||
197 | } | ||
198 | |||
199 | #endif /* !defined _LIBC || !defined GLOB_ONLY_P */ | ||
200 | |||
201 | /* Do glob searching for PATTERN, placing results in PGLOB. | ||
202 | The bits defined above may be set in FLAGS. | ||
203 | If a directory cannot be opened or read and ERRFUNC is not nil, | ||
204 | it is called with the pathname that caused the error, and the | ||
205 | `errno' value from the failing call; if it returns non-zero | ||
206 | `glob' returns GLOB_ABORTED; if it returns zero, the error is ignored. | ||
207 | If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned. | ||
208 | Otherwise, `glob' returns zero. */ | ||
209 | int | ||
210 | #ifdef GLOB_ATTRIBUTE | ||
211 | GLOB_ATTRIBUTE | ||
212 | #endif | ||
213 | glob (pattern, flags, errfunc, pglob) | ||
214 | const char *pattern; | ||
215 | int flags; | ||
216 | int (*errfunc) (const char *, int); | ||
217 | glob_t *pglob; | ||
218 | { | ||
219 | const char *filename; | ||
220 | const char *dirname; | ||
221 | size_t dirlen; | ||
222 | int status; | ||
223 | size_t oldcount; | ||
224 | |||
225 | if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0) | ||
226 | { | ||
227 | __set_errno (EINVAL); | ||
228 | return -1; | ||
229 | } | ||
230 | |||
231 | if (!(flags & GLOB_DOOFFS)) | ||
232 | /* Have to do this so `globfree' knows where to start freeing. It | ||
233 | also makes all the code that uses gl_offs simpler. */ | ||
234 | pglob->gl_offs = 0; | ||
235 | |||
236 | if (flags & GLOB_BRACE) | ||
237 | { | ||
238 | const char *begin; | ||
239 | |||
240 | if (flags & GLOB_NOESCAPE) | ||
241 | begin = strchr (pattern, '{'); | ||
242 | else | ||
243 | { | ||
244 | begin = pattern; | ||
245 | while (1) | ||
246 | { | ||
247 | if (*begin == '\0') | ||
248 | { | ||
249 | begin = NULL; | ||
250 | break; | ||
251 | } | ||
252 | |||
253 | if (*begin == '\\' && begin[1] != '\0') | ||
254 | ++begin; | ||
255 | else if (*begin == '{') | ||
256 | break; | ||
257 | |||
258 | ++begin; | ||
259 | } | ||
260 | } | ||
261 | |||
262 | if (begin != NULL) | ||
263 | { | ||
264 | /* Allocate working buffer large enough for our work. Note that | ||
265 | we have at least an opening and closing brace. */ | ||
266 | size_t firstc; | ||
267 | char *alt_start; | ||
268 | const char *p; | ||
269 | const char *next; | ||
270 | const char *rest; | ||
271 | size_t rest_len; | ||
272 | #ifdef __GNUC__ | ||
273 | char onealt[strlen (pattern) - 1]; | ||
274 | #else | ||
275 | char *onealt = malloc (strlen (pattern) - 1); | ||
276 | if (onealt == NULL) | ||
277 | { | ||
278 | if (!(flags & GLOB_APPEND)) | ||
279 | { | ||
280 | pglob->gl_pathc = 0; | ||
281 | pglob->gl_pathv = NULL; | ||
282 | } | ||
283 | return GLOB_NOSPACE; | ||
284 | } | ||
285 | #endif | ||
286 | |||
287 | /* We know the prefix for all sub-patterns. */ | ||
288 | alt_start = mempcpy (onealt, pattern, begin - pattern); | ||
289 | |||
290 | /* Find the first sub-pattern and at the same time find the | ||
291 | rest after the closing brace. */ | ||
292 | next = next_brace_sub (begin + 1, flags); | ||
293 | if (next == NULL) | ||
294 | { | ||
295 | /* It is an invalid expression. */ | ||
296 | #ifndef __GNUC__ | ||
297 | free (onealt); | ||
298 | #endif | ||
299 | return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob); | ||
300 | } | ||
301 | |||
302 | /* Now find the end of the whole brace expression. */ | ||
303 | rest = next; | ||
304 | while (*rest != '}') | ||
305 | { | ||
306 | rest = next_brace_sub (rest + 1, flags); | ||
307 | if (rest == NULL) | ||
308 | { | ||
309 | /* It is an invalid expression. */ | ||
310 | #ifndef __GNUC__ | ||
311 | free (onealt); | ||
312 | #endif | ||
313 | return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob); | ||
314 | } | ||
315 | } | ||
316 | /* Please note that we now can be sure the brace expression | ||
317 | is well-formed. */ | ||
318 | rest_len = strlen (++rest) + 1; | ||
319 | |||
320 | /* We have a brace expression. BEGIN points to the opening {, | ||
321 | NEXT points past the terminator of the first element, and END | ||
322 | points past the final }. We will accumulate result names from | ||
323 | recursive runs for each brace alternative in the buffer using | ||
324 | GLOB_APPEND. */ | ||
325 | |||
326 | if (!(flags & GLOB_APPEND)) | ||
327 | { | ||
328 | /* This call is to set a new vector, so clear out the | ||
329 | vector so we can append to it. */ | ||
330 | pglob->gl_pathc = 0; | ||
331 | pglob->gl_pathv = NULL; | ||
332 | } | ||
333 | firstc = pglob->gl_pathc; | ||
334 | |||
335 | p = begin + 1; | ||
336 | while (1) | ||
337 | { | ||
338 | int result; | ||
339 | |||
340 | /* Construct the new glob expression. */ | ||
341 | mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len); | ||
342 | |||
343 | result = glob (onealt, | ||
344 | ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC)) | ||
345 | | GLOB_APPEND), errfunc, pglob); | ||
346 | |||
347 | /* If we got an error, return it. */ | ||
348 | if (result && result != GLOB_NOMATCH) | ||
349 | { | ||
350 | #ifndef __GNUC__ | ||
351 | free (onealt); | ||
352 | #endif | ||
353 | if (!(flags & GLOB_APPEND)) | ||
354 | { | ||
355 | globfree (pglob); | ||
356 | pglob->gl_pathc = 0; | ||
357 | } | ||
358 | return result; | ||
359 | } | ||
360 | |||
361 | if (*next == '}') | ||
362 | /* We saw the last entry. */ | ||
363 | break; | ||
364 | |||
365 | p = next + 1; | ||
366 | next = next_brace_sub (p, flags); | ||
367 | assert (next != NULL); | ||
368 | } | ||
369 | |||
370 | #ifndef __GNUC__ | ||
371 | free (onealt); | ||
372 | #endif | ||
373 | |||
374 | if (pglob->gl_pathc != firstc) | ||
375 | /* We found some entries. */ | ||
376 | return 0; | ||
377 | else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC))) | ||
378 | return GLOB_NOMATCH; | ||
379 | } | ||
380 | } | ||
381 | |||
382 | /* Find the filename. */ | ||
383 | filename = strrchr (pattern, '/'); | ||
384 | #if defined __MSDOS__ || defined WINDOWS32 | ||
385 | /* The case of "d:pattern". Since `:' is not allowed in | ||
386 | file names, we can safely assume that wherever it | ||
387 | happens in pattern, it signals the filename part. This | ||
388 | is so we could some day support patterns like "[a-z]:foo". */ | ||
389 | if (filename == NULL) | ||
390 | filename = strchr (pattern, ':'); | ||
391 | #endif /* __MSDOS__ || WINDOWS32 */ | ||
392 | if (filename == NULL) | ||
393 | { | ||
394 | /* This can mean two things: a simple name or "~name". The latter | ||
395 | case is nothing but a notation for a directory. */ | ||
396 | if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~') | ||
397 | { | ||
398 | dirname = pattern; | ||
399 | dirlen = strlen (pattern); | ||
400 | |||
401 | /* Set FILENAME to NULL as a special flag. This is ugly but | ||
402 | other solutions would require much more code. We test for | ||
403 | this special case below. */ | ||
404 | filename = NULL; | ||
405 | } | ||
406 | else | ||
407 | { | ||
408 | filename = pattern; | ||
409 | #ifdef _AMIGA | ||
410 | dirname = ""; | ||
411 | #else | ||
412 | dirname = "."; | ||
413 | #endif | ||
414 | dirlen = 0; | ||
415 | } | ||
416 | } | ||
417 | else if (filename == pattern) | ||
418 | { | ||
419 | /* "/pattern". */ | ||
420 | dirname = "/"; | ||
421 | dirlen = 1; | ||
422 | ++filename; | ||
423 | } | ||
424 | else | ||
425 | { | ||
426 | char *newp; | ||
427 | dirlen = filename - pattern; | ||
428 | #if defined __MSDOS__ || defined WINDOWS32 | ||
429 | if (*filename == ':' | ||
430 | || (filename > pattern + 1 && filename[-1] == ':')) | ||
431 | { | ||
432 | char *drive_spec; | ||
433 | |||
434 | ++dirlen; | ||
435 | drive_spec = __alloca (dirlen + 1); | ||
436 | *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0'; | ||
437 | /* For now, disallow wildcards in the drive spec, to | ||
438 | prevent infinite recursion in glob. */ | ||
439 | if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE))) | ||
440 | return GLOB_NOMATCH; | ||
441 | /* If this is "d:pattern", we need to copy `:' to DIRNAME | ||
442 | as well. If it's "d:/pattern", don't remove the slash | ||
443 | from "d:/", since "d:" and "d:/" are not the same.*/ | ||
444 | } | ||
445 | #endif | ||
446 | newp = __alloca (dirlen + 1); | ||
447 | *((char *) mempcpy (newp, pattern, dirlen)) = '\0'; | ||
448 | dirname = newp; | ||
449 | ++filename; | ||
450 | |||
451 | if (filename[0] == '\0' | ||
452 | #if defined __MSDOS__ || defined WINDOWS32 | ||
453 | && dirname[dirlen - 1] != ':' | ||
454 | && (dirlen < 3 || dirname[dirlen - 2] != ':' | ||
455 | || dirname[dirlen - 1] != '/') | ||
456 | #endif | ||
457 | && dirlen > 1) | ||
458 | /* "pattern/". Expand "pattern", appending slashes. */ | ||
459 | { | ||
460 | int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob); | ||
461 | if (val == 0) | ||
462 | pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK) | ||
463 | | (flags & GLOB_MARK)); | ||
464 | return val; | ||
465 | } | ||
466 | } | ||
467 | |||
468 | if (!(flags & GLOB_APPEND)) | ||
469 | { | ||
470 | pglob->gl_pathc = 0; | ||
471 | if (!(flags & GLOB_DOOFFS)) | ||
472 | pglob->gl_pathv = NULL; | ||
473 | else | ||
474 | { | ||
475 | size_t i; | ||
476 | pglob->gl_pathv = malloc ((pglob->gl_offs + 1) * sizeof (char *)); | ||
477 | if (pglob->gl_pathv == NULL) | ||
478 | return GLOB_NOSPACE; | ||
479 | |||
480 | for (i = 0; i <= pglob->gl_offs; ++i) | ||
481 | pglob->gl_pathv[i] = NULL; | ||
482 | } | ||
483 | } | ||
484 | |||
485 | oldcount = pglob->gl_pathc + pglob->gl_offs; | ||
486 | |||
487 | if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~') | ||
488 | { | ||
489 | if (dirname[1] == '\0' || dirname[1] == '/') | ||
490 | { | ||
491 | /* Look up home directory. */ | ||
492 | const char *home_dir = getenv ("HOME"); | ||
493 | # ifdef _AMIGA | ||
494 | if (home_dir == NULL || home_dir[0] == '\0') | ||
495 | home_dir = "SYS:"; | ||
496 | # else | ||
497 | # ifdef WINDOWS32 | ||
498 | if (home_dir == NULL || home_dir[0] == '\0') | ||
499 | home_dir = "c:/users/default"; /* poor default */ | ||
500 | # else | ||
501 | if (home_dir == NULL || home_dir[0] == '\0') | ||
502 | { | ||
503 | int success; | ||
504 | char *name; | ||
505 | size_t buflen = GET_LOGIN_NAME_MAX () + 1; | ||
506 | |||
507 | if (buflen == 0) | ||
508 | /* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try | ||
509 | a moderate value. */ | ||
510 | buflen = 20; | ||
511 | name = __alloca (buflen); | ||
512 | |||
513 | success = getlogin_r (name, buflen) == 0; | ||
514 | if (success) | ||
515 | { | ||
516 | struct passwd *p; | ||
517 | # if defined HAVE_GETPWNAM_R || defined _LIBC | ||
518 | long int pwbuflen = GETPW_R_SIZE_MAX (); | ||
519 | char *pwtmpbuf; | ||
520 | struct passwd pwbuf; | ||
521 | int save = errno; | ||
522 | |||
523 | # ifndef _LIBC | ||
524 | if (pwbuflen == -1) | ||
525 | /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. | ||
526 | Try a moderate value. */ | ||
527 | pwbuflen = 1024; | ||
528 | # endif | ||
529 | pwtmpbuf = __alloca (pwbuflen); | ||
530 | |||
531 | while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p) | ||
532 | != 0) | ||
533 | { | ||
534 | if (errno != ERANGE) | ||
535 | { | ||
536 | p = NULL; | ||
537 | break; | ||
538 | } | ||
539 | # ifdef _LIBC | ||
540 | pwtmpbuf = extend_alloca (pwtmpbuf, pwbuflen, | ||
541 | 2 * pwbuflen); | ||
542 | # else | ||
543 | pwbuflen *= 2; | ||
544 | pwtmpbuf = __alloca (pwbuflen); | ||
545 | # endif | ||
546 | __set_errno (save); | ||
547 | } | ||
548 | # else | ||
549 | p = getpwnam (name); | ||
550 | # endif | ||
551 | if (p != NULL) | ||
552 | home_dir = p->pw_dir; | ||
553 | } | ||
554 | } | ||
555 | if (home_dir == NULL || home_dir[0] == '\0') | ||
556 | { | ||
557 | if (flags & GLOB_TILDE_CHECK) | ||
558 | return GLOB_NOMATCH; | ||
559 | else | ||
560 | home_dir = "~"; /* No luck. */ | ||
561 | } | ||
562 | # endif /* WINDOWS32 */ | ||
563 | # endif | ||
564 | /* Now construct the full directory. */ | ||
565 | if (dirname[1] == '\0') | ||
566 | dirname = home_dir; | ||
567 | else | ||
568 | { | ||
569 | char *newp; | ||
570 | size_t home_len = strlen (home_dir); | ||
571 | newp = __alloca (home_len + dirlen); | ||
572 | mempcpy (mempcpy (newp, home_dir, home_len), | ||
573 | &dirname[1], dirlen); | ||
574 | dirname = newp; | ||
575 | } | ||
576 | } | ||
577 | # if !defined _AMIGA && !defined WINDOWS32 | ||
578 | else | ||
579 | { | ||
580 | char *end_name = strchr (dirname, '/'); | ||
581 | const char *user_name; | ||
582 | const char *home_dir; | ||
583 | |||
584 | if (end_name == NULL) | ||
585 | user_name = dirname + 1; | ||
586 | else | ||
587 | { | ||
588 | char *newp; | ||
589 | newp = __alloca (end_name - dirname); | ||
590 | *((char *) mempcpy (newp, dirname + 1, end_name - dirname)) | ||
591 | = '\0'; | ||
592 | user_name = newp; | ||
593 | } | ||
594 | |||
595 | /* Look up specific user's home directory. */ | ||
596 | { | ||
597 | struct passwd *p; | ||
598 | # if defined HAVE_GETPWNAM_R || defined _LIBC | ||
599 | long int buflen = GETPW_R_SIZE_MAX (); | ||
600 | char *pwtmpbuf; | ||
601 | struct passwd pwbuf; | ||
602 | int save = errno; | ||
603 | |||
604 | # ifndef _LIBC | ||
605 | if (buflen == -1) | ||
606 | /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a | ||
607 | moderate value. */ | ||
608 | buflen = 1024; | ||
609 | # endif | ||
610 | pwtmpbuf = __alloca (buflen); | ||
611 | |||
612 | while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0) | ||
613 | { | ||
614 | if (errno != ERANGE) | ||
615 | { | ||
616 | p = NULL; | ||
617 | break; | ||
618 | } | ||
619 | # ifdef _LIBC | ||
620 | pwtmpbuf = extend_alloca (pwtmpbuf, buflen, 2 * buflen); | ||
621 | # else | ||
622 | buflen *= 2; | ||
623 | pwtmpbuf = __alloca (buflen); | ||
624 | # endif | ||
625 | __set_errno (save); | ||
626 | } | ||
627 | # else | ||
628 | p = getpwnam (user_name); | ||
629 | # endif | ||
630 | if (p != NULL) | ||
631 | home_dir = p->pw_dir; | ||
632 | else | ||
633 | home_dir = NULL; | ||
634 | } | ||
635 | /* If we found a home directory use this. */ | ||
636 | if (home_dir != NULL) | ||
637 | { | ||
638 | char *newp; | ||
639 | size_t home_len = strlen (home_dir); | ||
640 | size_t rest_len = end_name == NULL ? 0 : strlen (end_name); | ||
641 | newp = __alloca (home_len + rest_len + 1); | ||
642 | *((char *) mempcpy (mempcpy (newp, home_dir, home_len), | ||
643 | end_name, rest_len)) = '\0'; | ||
644 | dirname = newp; | ||
645 | } | ||
646 | else | ||
647 | if (flags & GLOB_TILDE_CHECK) | ||
648 | /* We have to regard it as an error if we cannot find the | ||
649 | home directory. */ | ||
650 | return GLOB_NOMATCH; | ||
651 | } | ||
652 | # endif /* Not Amiga && not WINDOWS32. */ | ||
653 | } | ||
654 | |||
655 | /* Now test whether we looked for "~" or "~NAME". In this case we | ||
656 | can give the answer now. */ | ||
657 | if (filename == NULL) | ||
658 | { | ||
659 | struct stat st; | ||
660 | struct_stat64 st64; | ||
661 | |||
662 | /* Return the directory if we don't check for error or if it exists. */ | ||
663 | if ((flags & GLOB_NOCHECK) | ||
664 | || (((flags & GLOB_ALTDIRFUNC) | ||
665 | ? ((*pglob->gl_stat) (dirname, &st) == 0 | ||
666 | && S_ISDIR (st.st_mode)) | ||
667 | : (__stat64 (dirname, &st64) == 0 && S_ISDIR (st64.st_mode))))) | ||
668 | { | ||
669 | int newcount = pglob->gl_pathc + pglob->gl_offs; | ||
670 | char **new_gl_pathv; | ||
671 | |||
672 | new_gl_pathv | ||
673 | = realloc (pglob->gl_pathv, (newcount + 1 + 1) * sizeof (char *)); | ||
674 | if (new_gl_pathv == NULL) | ||
675 | { | ||
676 | nospace: | ||
677 | free (pglob->gl_pathv); | ||
678 | pglob->gl_pathv = NULL; | ||
679 | pglob->gl_pathc = 0; | ||
680 | return GLOB_NOSPACE; | ||
681 | } | ||
682 | pglob->gl_pathv = new_gl_pathv; | ||
683 | |||
684 | pglob->gl_pathv[newcount] = strdup (dirname); | ||
685 | if (pglob->gl_pathv[newcount] == NULL) | ||
686 | goto nospace; | ||
687 | pglob->gl_pathv[++newcount] = NULL; | ||
688 | ++pglob->gl_pathc; | ||
689 | pglob->gl_flags = flags; | ||
690 | |||
691 | return 0; | ||
692 | } | ||
693 | |||
694 | /* Not found. */ | ||
695 | return GLOB_NOMATCH; | ||
696 | } | ||
697 | |||
698 | if (__glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE))) | ||
699 | { | ||
700 | /* The directory name contains metacharacters, so we | ||
701 | have to glob for the directory, and then glob for | ||
702 | the pattern in each directory found. */ | ||
703 | glob_t dirs; | ||
704 | size_t i; | ||
705 | |||
706 | if ((flags & GLOB_ALTDIRFUNC) != 0) | ||
707 | { | ||
708 | /* Use the alternative access functions also in the recursive | ||
709 | call. */ | ||
710 | dirs.gl_opendir = pglob->gl_opendir; | ||
711 | dirs.gl_readdir = pglob->gl_readdir; | ||
712 | dirs.gl_closedir = pglob->gl_closedir; | ||
713 | dirs.gl_stat = pglob->gl_stat; | ||
714 | dirs.gl_lstat = pglob->gl_lstat; | ||
715 | } | ||
716 | |||
717 | status = glob (dirname, | ||
718 | ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE | ||
719 | | GLOB_ALTDIRFUNC)) | ||
720 | | GLOB_NOSORT | GLOB_ONLYDIR), | ||
721 | errfunc, &dirs); | ||
722 | if (status != 0) | ||
723 | return status; | ||
724 | |||
725 | /* We have successfully globbed the preceding directory name. | ||
726 | For each name we found, call glob_in_dir on it and FILENAME, | ||
727 | appending the results to PGLOB. */ | ||
728 | for (i = 0; i < dirs.gl_pathc; ++i) | ||
729 | { | ||
730 | int old_pathc; | ||
731 | |||
732 | #ifdef SHELL | ||
733 | { | ||
734 | /* Make globbing interruptible in the bash shell. */ | ||
735 | extern int interrupt_state; | ||
736 | |||
737 | if (interrupt_state) | ||
738 | { | ||
739 | globfree (&dirs); | ||
740 | return GLOB_ABORTED; | ||
741 | } | ||
742 | } | ||
743 | #endif /* SHELL. */ | ||
744 | |||
745 | old_pathc = pglob->gl_pathc; | ||
746 | status = glob_in_dir (filename, dirs.gl_pathv[i], | ||
747 | ((flags | GLOB_APPEND) | ||
748 | & ~(GLOB_NOCHECK | GLOB_NOMAGIC)), | ||
749 | errfunc, pglob); | ||
750 | if (status == GLOB_NOMATCH) | ||
751 | /* No matches in this directory. Try the next. */ | ||
752 | continue; | ||
753 | |||
754 | if (status != 0) | ||
755 | { | ||
756 | globfree (&dirs); | ||
757 | globfree (pglob); | ||
758 | pglob->gl_pathc = 0; | ||
759 | return status; | ||
760 | } | ||
761 | |||
762 | /* Stick the directory on the front of each name. */ | ||
763 | if (prefix_array (dirs.gl_pathv[i], | ||
764 | &pglob->gl_pathv[old_pathc + pglob->gl_offs], | ||
765 | pglob->gl_pathc - old_pathc)) | ||
766 | { | ||
767 | globfree (&dirs); | ||
768 | globfree (pglob); | ||
769 | pglob->gl_pathc = 0; | ||
770 | return GLOB_NOSPACE; | ||
771 | } | ||
772 | } | ||
773 | |||
774 | flags |= GLOB_MAGCHAR; | ||
775 | |||
776 | /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls. | ||
777 | But if we have not found any matching entry and the GLOB_NOCHECK | ||
778 | flag was set we must return the input pattern itself. */ | ||
779 | if (pglob->gl_pathc + pglob->gl_offs == oldcount) | ||
780 | { | ||
781 | /* No matches. */ | ||
782 | if (flags & GLOB_NOCHECK) | ||
783 | { | ||
784 | int newcount = pglob->gl_pathc + pglob->gl_offs; | ||
785 | char **new_gl_pathv; | ||
786 | |||
787 | new_gl_pathv = realloc (pglob->gl_pathv, | ||
788 | (newcount + 2) * sizeof (char *)); | ||
789 | if (new_gl_pathv == NULL) | ||
790 | { | ||
791 | globfree (&dirs); | ||
792 | return GLOB_NOSPACE; | ||
793 | } | ||
794 | pglob->gl_pathv = new_gl_pathv; | ||
795 | |||
796 | pglob->gl_pathv[newcount] = strdup (pattern); | ||
797 | if (pglob->gl_pathv[newcount] == NULL) | ||
798 | { | ||
799 | globfree (&dirs); | ||
800 | globfree (pglob); | ||
801 | pglob->gl_pathc = 0; | ||
802 | return GLOB_NOSPACE; | ||
803 | } | ||
804 | |||
805 | ++pglob->gl_pathc; | ||
806 | ++newcount; | ||
807 | |||
808 | pglob->gl_pathv[newcount] = NULL; | ||
809 | pglob->gl_flags = flags; | ||
810 | } | ||
811 | else | ||
812 | { | ||
813 | globfree (&dirs); | ||
814 | return GLOB_NOMATCH; | ||
815 | } | ||
816 | } | ||
817 | |||
818 | globfree (&dirs); | ||
819 | } | ||
820 | else | ||
821 | { | ||
822 | int old_pathc = pglob->gl_pathc; | ||
823 | |||
824 | status = glob_in_dir (filename, dirname, flags, errfunc, pglob); | ||
825 | if (status != 0) | ||
826 | return status; | ||
827 | |||
828 | if (dirlen > 0) | ||
829 | { | ||
830 | /* Stick the directory on the front of each name. */ | ||
831 | if (prefix_array (dirname, | ||
832 | &pglob->gl_pathv[old_pathc + pglob->gl_offs], | ||
833 | pglob->gl_pathc - old_pathc)) | ||
834 | { | ||
835 | globfree (pglob); | ||
836 | pglob->gl_pathc = 0; | ||
837 | return GLOB_NOSPACE; | ||
838 | } | ||
839 | } | ||
840 | } | ||
841 | |||
842 | if (!(flags & GLOB_NOSORT)) | ||
843 | { | ||
844 | /* Sort the vector. */ | ||
845 | qsort (&pglob->gl_pathv[oldcount], | ||
846 | pglob->gl_pathc + pglob->gl_offs - oldcount, | ||
847 | sizeof (char *), collated_compare); | ||
848 | } | ||
849 | |||
850 | return 0; | ||
851 | } | ||
852 | #if defined _LIBC && !defined glob | ||
853 | libc_hidden_def (glob) | ||
854 | #endif | ||
855 | |||
856 | |||
857 | #if !defined _LIBC || !defined GLOB_ONLY_P | ||
858 | |||
859 | /* Free storage allocated in PGLOB by a previous `glob' call. */ | ||
860 | void | ||
861 | globfree (pglob) | ||
862 | register glob_t *pglob; | ||
863 | { | ||
864 | if (pglob->gl_pathv != NULL) | ||
865 | { | ||
866 | size_t i; | ||
867 | for (i = 0; i < pglob->gl_pathc; ++i) | ||
868 | if (pglob->gl_pathv[pglob->gl_offs + i] != NULL) | ||
869 | free (pglob->gl_pathv[pglob->gl_offs + i]); | ||
870 | free (pglob->gl_pathv); | ||
871 | pglob->gl_pathv = NULL; | ||
872 | } | ||
873 | } | ||
874 | #if defined _LIBC && !defined globfree | ||
875 | libc_hidden_def (globfree) | ||
876 | #endif | ||
877 | |||
878 | |||
879 | /* Do a collated comparison of A and B. */ | ||
880 | static int | ||
881 | collated_compare (const void *a, const void *b) | ||
882 | { | ||
883 | char *const *ps1 = a; char *s1 = *ps1; | ||
884 | char *const *ps2 = b; char *s2 = *ps2; | ||
885 | |||
886 | if (s1 == s2) | ||
887 | return 0; | ||
888 | if (s1 == NULL) | ||
889 | return 1; | ||
890 | if (s2 == NULL) | ||
891 | return -1; | ||
892 | return strcoll (s1, s2); | ||
893 | } | ||
894 | |||
895 | |||
896 | /* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's | ||
897 | elements in place. Return nonzero if out of memory, zero if successful. | ||
898 | A slash is inserted between DIRNAME and each elt of ARRAY, | ||
899 | unless DIRNAME is just "/". Each old element of ARRAY is freed. */ | ||
900 | static int | ||
901 | prefix_array (const char *dirname, char **array, size_t n) | ||
902 | { | ||
903 | register size_t i; | ||
904 | size_t dirlen = strlen (dirname); | ||
905 | #if defined __MSDOS__ || defined WINDOWS32 | ||
906 | int sep_char = '/'; | ||
907 | # define DIRSEP_CHAR sep_char | ||
908 | #else | ||
909 | # define DIRSEP_CHAR '/' | ||
910 | #endif | ||
911 | |||
912 | if (dirlen == 1 && dirname[0] == '/') | ||
913 | /* DIRNAME is just "/", so normal prepending would get us "//foo". | ||
914 | We want "/foo" instead, so don't prepend any chars from DIRNAME. */ | ||
915 | dirlen = 0; | ||
916 | #if defined __MSDOS__ || defined WINDOWS32 | ||
917 | else if (dirlen > 1) | ||
918 | { | ||
919 | if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':') | ||
920 | /* DIRNAME is "d:/". Don't prepend the slash from DIRNAME. */ | ||
921 | --dirlen; | ||
922 | else if (dirname[dirlen - 1] == ':') | ||
923 | { | ||
924 | /* DIRNAME is "d:". Use `:' instead of `/'. */ | ||
925 | --dirlen; | ||
926 | sep_char = ':'; | ||
927 | } | ||
928 | } | ||
929 | #endif | ||
930 | |||
931 | for (i = 0; i < n; ++i) | ||
932 | { | ||
933 | size_t eltlen = strlen (array[i]) + 1; | ||
934 | char *new = malloc (dirlen + 1 + eltlen); | ||
935 | if (new == NULL) | ||
936 | { | ||
937 | while (i > 0) | ||
938 | free (array[--i]); | ||
939 | return 1; | ||
940 | } | ||
941 | |||
942 | { | ||
943 | char *endp = mempcpy (new, dirname, dirlen); | ||
944 | *endp++ = DIRSEP_CHAR; | ||
945 | mempcpy (endp, array[i], eltlen); | ||
946 | } | ||
947 | free (array[i]); | ||
948 | array[i] = new; | ||
949 | } | ||
950 | |||
951 | return 0; | ||
952 | } | ||
953 | |||
954 | |||
955 | /* We must not compile this function twice. */ | ||
956 | #if !defined _LIBC || !defined NO_GLOB_PATTERN_P | ||
957 | /* Return nonzero if PATTERN contains any metacharacters. | ||
958 | Metacharacters can be quoted with backslashes if QUOTE is nonzero. */ | ||
959 | int | ||
960 | __glob_pattern_p (pattern, quote) | ||
961 | const char *pattern; | ||
962 | int quote; | ||
963 | { | ||
964 | register const char *p; | ||
965 | int open = 0; | ||
966 | |||
967 | for (p = pattern; *p != '\0'; ++p) | ||
968 | switch (*p) | ||
969 | { | ||
970 | case '?': | ||
971 | case '*': | ||
972 | return 1; | ||
973 | |||
974 | case '\\': | ||
975 | if (quote && p[1] != '\0') | ||
976 | ++p; | ||
977 | break; | ||
978 | |||
979 | case '[': | ||
980 | open = 1; | ||
981 | break; | ||
982 | |||
983 | case ']': | ||
984 | if (open) | ||
985 | return 1; | ||
986 | break; | ||
987 | } | ||
988 | |||
989 | return 0; | ||
990 | } | ||
991 | # ifdef _LIBC | ||
992 | weak_alias (__glob_pattern_p, glob_pattern_p) | ||
993 | # endif | ||
994 | #endif | ||
995 | |||
996 | #endif /* !GLOB_ONLY_P */ | ||
997 | |||
998 | |||
999 | /* We put this in a separate function mainly to allow the memory | ||
1000 | allocated with alloca to be recycled. */ | ||
1001 | #if !defined _LIBC || !defined GLOB_ONLY_P | ||
1002 | static bool | ||
1003 | is_dir_p (const char *dir, size_t dirlen, const char *fname, | ||
1004 | glob_t *pglob, int flags) | ||
1005 | { | ||
1006 | size_t fnamelen = strlen (fname); | ||
1007 | char *fullname = __alloca (dirlen + 1 + fnamelen + 1); | ||
1008 | struct stat st; | ||
1009 | struct_stat64 st64; | ||
1010 | |||
1011 | mempcpy (mempcpy (mempcpy (fullname, dir, dirlen), "/", 1), | ||
1012 | fname, fnamelen + 1); | ||
1013 | |||
1014 | return ((flags & GLOB_ALTDIRFUNC) | ||
1015 | ? (*pglob->gl_stat) (fullname, &st) == 0 && S_ISDIR (st.st_mode) | ||
1016 | : __stat64 (fullname, &st64) == 0 && S_ISDIR (st64.st_mode)); | ||
1017 | } | ||
1018 | #endif | ||
1019 | |||
1020 | |||
1021 | /* Like `glob', but PATTERN is a final pathname component, | ||
1022 | and matches are searched for in DIRECTORY. | ||
1023 | The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done. | ||
1024 | The GLOB_APPEND flag is assumed to be set (always appends). */ | ||
1025 | static int | ||
1026 | glob_in_dir (const char *pattern, const char *directory, int flags, | ||
1027 | int (*errfunc) (const char *, int), | ||
1028 | glob_t *pglob) | ||
1029 | { | ||
1030 | size_t dirlen = strlen (directory); | ||
1031 | void *stream = NULL; | ||
1032 | struct globlink | ||
1033 | { | ||
1034 | struct globlink *next; | ||
1035 | char *name; | ||
1036 | }; | ||
1037 | struct globlink *names = NULL; | ||
1038 | size_t nfound; | ||
1039 | int meta; | ||
1040 | int save; | ||
1041 | |||
1042 | meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)); | ||
1043 | if (meta == 0 && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC))) | ||
1044 | { | ||
1045 | /* We need not do any tests. The PATTERN contains no meta | ||
1046 | characters and we must not return an error therefore the | ||
1047 | result will always contain exactly one name. */ | ||
1048 | flags |= GLOB_NOCHECK; | ||
1049 | nfound = 0; | ||
1050 | } | ||
1051 | else if (meta == 0 && | ||
1052 | ((flags & GLOB_NOESCAPE) || strchr (pattern, '\\') == NULL)) | ||
1053 | { | ||
1054 | /* Since we use the normal file functions we can also use stat() | ||
1055 | to verify the file is there. */ | ||
1056 | struct stat st; | ||
1057 | struct_stat64 st64; | ||
1058 | size_t patlen = strlen (pattern); | ||
1059 | char *fullname = __alloca (dirlen + 1 + patlen + 1); | ||
1060 | |||
1061 | mempcpy (mempcpy (mempcpy (fullname, directory, dirlen), | ||
1062 | "/", 1), | ||
1063 | pattern, patlen + 1); | ||
1064 | if (((flags & GLOB_ALTDIRFUNC) | ||
1065 | ? (*pglob->gl_stat) (fullname, &st) | ||
1066 | : __stat64 (fullname, &st64)) == 0) | ||
1067 | /* We found this file to be existing. Now tell the rest | ||
1068 | of the function to copy this name into the result. */ | ||
1069 | flags |= GLOB_NOCHECK; | ||
1070 | |||
1071 | nfound = 0; | ||
1072 | } | ||
1073 | else | ||
1074 | { | ||
1075 | if (pattern[0] == '\0') | ||
1076 | { | ||
1077 | /* This is a special case for matching directories like in | ||
1078 | "*a/". */ | ||
1079 | names = __alloca (sizeof (struct globlink)); | ||
1080 | names->name = malloc (1); | ||
1081 | if (names->name == NULL) | ||
1082 | goto memory_error; | ||
1083 | names->name[0] = '\0'; | ||
1084 | names->next = NULL; | ||
1085 | nfound = 1; | ||
1086 | meta = 0; | ||
1087 | } | ||
1088 | else | ||
1089 | { | ||
1090 | stream = ((flags & GLOB_ALTDIRFUNC) | ||
1091 | ? (*pglob->gl_opendir) (directory) | ||
1092 | : opendir (directory)); | ||
1093 | if (stream == NULL) | ||
1094 | { | ||
1095 | if (errno != ENOTDIR | ||
1096 | && ((errfunc != NULL && (*errfunc) (directory, errno)) | ||
1097 | || (flags & GLOB_ERR))) | ||
1098 | return GLOB_ABORTED; | ||
1099 | nfound = 0; | ||
1100 | meta = 0; | ||
1101 | } | ||
1102 | else | ||
1103 | { | ||
1104 | int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) | ||
1105 | | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0) | ||
1106 | #if defined _AMIGA || defined __VMS | ||
1107 | | FNM_CASEFOLD | ||
1108 | #endif | ||
1109 | ); | ||
1110 | nfound = 0; | ||
1111 | flags |= GLOB_MAGCHAR; | ||
1112 | |||
1113 | while (1) | ||
1114 | { | ||
1115 | const char *name; | ||
1116 | size_t len; | ||
1117 | #if defined _LIBC && !defined COMPILE_GLOB64 | ||
1118 | struct dirent64 *d; | ||
1119 | union | ||
1120 | { | ||
1121 | struct dirent64 d64; | ||
1122 | char room [offsetof (struct dirent64, d_name[0]) | ||
1123 | + NAME_MAX + 1]; | ||
1124 | } | ||
1125 | d64buf; | ||
1126 | |||
1127 | if (flags & GLOB_ALTDIRFUNC) | ||
1128 | { | ||
1129 | struct dirent *d32 = (*pglob->gl_readdir) (stream); | ||
1130 | if (d32 != NULL) | ||
1131 | { | ||
1132 | CONVERT_DIRENT_DIRENT64 (&d64buf.d64, d32); | ||
1133 | d = &d64buf.d64; | ||
1134 | } | ||
1135 | else | ||
1136 | d = NULL; | ||
1137 | } | ||
1138 | else | ||
1139 | d = __readdir64 (stream); | ||
1140 | #else | ||
1141 | struct dirent *d = ((flags & GLOB_ALTDIRFUNC) | ||
1142 | ? ((*pglob->gl_readdir) (stream)) | ||
1143 | : __readdir (stream)); | ||
1144 | #endif | ||
1145 | if (d == NULL) | ||
1146 | break; | ||
1147 | if (! REAL_DIR_ENTRY (d)) | ||
1148 | continue; | ||
1149 | |||
1150 | /* If we shall match only directories use the information | ||
1151 | provided by the dirent call if possible. */ | ||
1152 | if ((flags & GLOB_ONLYDIR) && !DIRENT_MIGHT_BE_DIR (d)) | ||
1153 | continue; | ||
1154 | |||
1155 | name = d->d_name; | ||
1156 | |||
1157 | if (fnmatch (pattern, name, fnm_flags) == 0) | ||
1158 | { | ||
1159 | /* ISDIR will often be incorrectly set to false | ||
1160 | when not in GLOB_ONLYDIR || GLOB_MARK mode, but we | ||
1161 | don't care. It won't be used and we save the | ||
1162 | expensive call to stat. */ | ||
1163 | int need_dir_test = | ||
1164 | (GLOB_MARK | (DIRENT_MIGHT_BE_SYMLINK (d) | ||
1165 | ? GLOB_ONLYDIR : 0)); | ||
1166 | bool isdir = (DIRENT_MUST_BE (d, DT_DIR) | ||
1167 | || ((flags & need_dir_test) | ||
1168 | && is_dir_p (directory, dirlen, name, | ||
1169 | pglob, flags))); | ||
1170 | |||
1171 | /* In GLOB_ONLYDIR mode, skip non-dirs. */ | ||
1172 | if ((flags & GLOB_ONLYDIR) && !isdir) | ||
1173 | continue; | ||
1174 | |||
1175 | { | ||
1176 | struct globlink *new = | ||
1177 | __alloca (sizeof (struct globlink)); | ||
1178 | char *p; | ||
1179 | len = _D_EXACT_NAMLEN (d); | ||
1180 | new->name = | ||
1181 | malloc (len + 1 + ((flags & GLOB_MARK) && isdir)); | ||
1182 | if (new->name == NULL) | ||
1183 | goto memory_error; | ||
1184 | p = mempcpy (new->name, name, len); | ||
1185 | if ((flags & GLOB_MARK) && isdir) | ||
1186 | *p++ = '/'; | ||
1187 | *p = '\0'; | ||
1188 | new->next = names; | ||
1189 | names = new; | ||
1190 | ++nfound; | ||
1191 | } | ||
1192 | } | ||
1193 | } | ||
1194 | } | ||
1195 | } | ||
1196 | } | ||
1197 | |||
1198 | if (nfound == 0 && (flags & GLOB_NOCHECK)) | ||
1199 | { | ||
1200 | size_t len = strlen (pattern); | ||
1201 | nfound = 1; | ||
1202 | names = __alloca (sizeof (struct globlink)); | ||
1203 | names->next = NULL; | ||
1204 | names->name = malloc (len + 1); | ||
1205 | if (names->name == NULL) | ||
1206 | goto memory_error; | ||
1207 | *((char *) mempcpy (names->name, pattern, len)) = '\0'; | ||
1208 | } | ||
1209 | |||
1210 | if (nfound != 0) | ||
1211 | { | ||
1212 | char **new_gl_pathv; | ||
1213 | |||
1214 | new_gl_pathv | ||
1215 | = realloc (pglob->gl_pathv, | ||
1216 | (pglob->gl_pathc + pglob->gl_offs + nfound + 1) | ||
1217 | * sizeof (char *)); | ||
1218 | if (new_gl_pathv == NULL) | ||
1219 | goto memory_error; | ||
1220 | pglob->gl_pathv = new_gl_pathv; | ||
1221 | |||
1222 | for (; names != NULL; names = names->next) | ||
1223 | pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc++] = names->name; | ||
1224 | pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; | ||
1225 | |||
1226 | pglob->gl_flags = flags; | ||
1227 | } | ||
1228 | |||
1229 | save = errno; | ||
1230 | if (stream != NULL) | ||
1231 | { | ||
1232 | if (flags & GLOB_ALTDIRFUNC) | ||
1233 | (*pglob->gl_closedir) (stream); | ||
1234 | else | ||
1235 | closedir (stream); | ||
1236 | } | ||
1237 | __set_errno (save); | ||
1238 | |||
1239 | return nfound == 0 ? GLOB_NOMATCH : 0; | ||
1240 | |||
1241 | memory_error: | ||
1242 | { | ||
1243 | int save = errno; | ||
1244 | if (flags & GLOB_ALTDIRFUNC) | ||
1245 | (*pglob->gl_closedir) (stream); | ||
1246 | else | ||
1247 | closedir (stream); | ||
1248 | __set_errno (save); | ||
1249 | } | ||
1250 | while (names != NULL) | ||
1251 | { | ||
1252 | if (names->name != NULL) | ||
1253 | free (names->name); | ||
1254 | names = names->next; | ||
1255 | } | ||
1256 | return GLOB_NOSPACE; | ||
1257 | } |
mailbox/glob_.h
deleted
100644 → 0
1 | /* glob_.h -- Find a path matching a pattern. | ||
2 | |||
3 | Copyright (C) 2005, 2006 Free Software Foundation, Inc. | ||
4 | |||
5 | Written by Derek Price <derek@ximbiot.com> & Paul Eggert <eggert@CS.UCLA.EDU> | ||
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 | #ifndef GLOB_H | ||
22 | #define GLOB_H 1 | ||
23 | |||
24 | #ifdef HAVE_SYS_CDEFS_H | ||
25 | # include <sys/cdefs.h> | ||
26 | #endif | ||
27 | |||
28 | #include <stddef.h> | ||
29 | |||
30 | #ifndef __BEGIN_DECLS | ||
31 | # define __BEGIN_DECLS | ||
32 | # define __END_DECLS | ||
33 | #endif | ||
34 | #ifndef __THROW | ||
35 | # define __THROW | ||
36 | #endif | ||
37 | |||
38 | #ifndef __size_t | ||
39 | # define __size_t size_t | ||
40 | #endif | ||
41 | #ifndef __restrict | ||
42 | # define __restrict restrict | ||
43 | #endif | ||
44 | #ifndef __USE_GNU | ||
45 | # define __USE_GNU 1 | ||
46 | #endif | ||
47 | |||
48 | |||
49 | #define glob rpl_glob | ||
50 | #define globfree rpl_globfree | ||
51 | #define glob_pattern_p rpl_glob_pattern_p | ||
52 | |||
53 | #define __GLOB_GNULIB 1 | ||
54 | |||
55 | /* Now the standard GNU C Library header should work. */ | ||
56 | #include "glob-libc.h" | ||
57 | |||
58 | #endif /* GLOB_H */ |
mailbox/malloc.c
deleted
100644 → 0
1 | /* malloc() function that is glibc compatible. | ||
2 | Copyright (C) 1997, 1998 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 | #ifdef HAVE_CONFIG_H | ||
21 | # include <config.h> | ||
22 | #endif | ||
23 | #undef malloc | ||
24 | |||
25 | #include <stdlib.h> | ||
26 | |||
27 | /* Allocate an N-byte block of memory from the heap. | ||
28 | If N is zero, allocate a 1-byte block. */ | ||
29 | |||
30 | void * | ||
31 | rpl_malloc (size_t n) | ||
32 | { | ||
33 | if (n == 0) | ||
34 | n = 1; | ||
35 | return malloc (n); | ||
36 | } |
mailbox/mbchar.c
deleted
100644 → 0
1 | /* Copyright (C) 2001 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 | #ifdef HAVE_CONFIG_H | ||
19 | # include <config.h> | ||
20 | #endif | ||
21 | |||
22 | #include <limits.h> | ||
23 | |||
24 | #include "mbchar.h" | ||
25 | |||
26 | #if IS_BASIC_ASCII | ||
27 | |||
28 | /* Bit table of characters in the ISO C "basic character set". */ | ||
29 | unsigned int is_basic_table [UCHAR_MAX / 32 + 1] = | ||
30 | { | ||
31 | 0x00001a00, /* '\t' '\v' '\f' */ | ||
32 | 0xffffffef, /* ' '...'#' '%'...'?' */ | ||
33 | 0xfffffffe, /* 'A'...'Z' '[' '\\' ']' '^' '_' */ | ||
34 | 0x7ffffffe /* 'a'...'z' '{' '|' '}' '~' */ | ||
35 | /* The remaining bits are 0. */ | ||
36 | }; | ||
37 | |||
38 | #endif /* IS_BASIC_ASCII */ |
mailbox/mbchar.h
deleted
100644 → 0
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 | |||
159 | /* BeOS 5 has the functions but no <wctype.h>. */ | ||
160 | #if HAVE_WCTYPE_H | ||
161 | # include <wctype.h> | ||
162 | #endif | ||
163 | /* FreeBSD 4.4 to 4.11 has <wctype.h> but lacks the functions. | ||
164 | Assume all 12 functions are implemented the same way, or not at all. */ | ||
165 | #if !defined iswalnum && !HAVE_ISWCNTRL | ||
166 | static inline int | ||
167 | iswalnum (wint_t wc) | ||
168 | { | ||
169 | return (wc >= 0 && wc < 128 | ||
170 | ? (wc >= '0' && wc <= '9') || ((wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'Z') | ||
171 | : 0); | ||
172 | } | ||
173 | # define iswalnum iswalnum | ||
174 | #endif | ||
175 | #if !defined iswalpha && !HAVE_ISWCNTRL | ||
176 | static inline int | ||
177 | iswalpha (wint_t wc) | ||
178 | { | ||
179 | return (wc >= 0 && wc < 128 | ||
180 | ? (wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'Z' | ||
181 | : 0); | ||
182 | } | ||
183 | # define iswalpha iswalpha | ||
184 | #endif | ||
185 | #if !defined iswblank && !HAVE_ISWCNTRL | ||
186 | static inline int | ||
187 | iswblank (wint_t wc) | ||
188 | { | ||
189 | return (wc >= 0 && wc < 128 | ||
190 | ? wc == ' ' || wc == '\t' | ||
191 | : 0); | ||
192 | } | ||
193 | # define iswblank iswblank | ||
194 | #endif | ||
195 | #if !defined iswcntrl && !HAVE_ISWCNTRL | ||
196 | static inline int | ||
197 | iswcntrl (wint_t wc) | ||
198 | { | ||
199 | return (wc >= 0 && wc < 128 | ||
200 | ? (wc & ~0x1f) == 0 || wc == 0x7f | ||
201 | : 0); | ||
202 | } | ||
203 | # define iswcntrl iswcntrl | ||
204 | #endif | ||
205 | #if !defined iswdigit && !HAVE_ISWCNTRL | ||
206 | static inline int | ||
207 | iswdigit (wint_t wc) | ||
208 | { | ||
209 | return (wc >= '0' && wc <= '9'); | ||
210 | } | ||
211 | # define iswdigit iswdigit | ||
212 | #endif | ||
213 | #if !defined iswgraph && !HAVE_ISWCNTRL | ||
214 | static inline int | ||
215 | iswgraph (wint_t wc) | ||
216 | { | ||
217 | return (wc >= 0 && wc < 128 | ||
218 | ? wc >= '!' && wc <= '~' | ||
219 | : 1); | ||
220 | } | ||
221 | # define iswgraph iswgraph | ||
222 | #endif | ||
223 | #if !defined iswlower && !HAVE_ISWCNTRL | ||
224 | static inline int | ||
225 | iswlower (wint_t wc) | ||
226 | { | ||
227 | return (wc >= 0 && wc < 128 | ||
228 | ? wc >= 'a' && wc <= 'z' | ||
229 | : 0); | ||
230 | } | ||
231 | # define iswlower iswlower | ||
232 | #endif | ||
233 | #if !defined iswprint && !HAVE_ISWCNTRL | ||
234 | static inline int | ||
235 | iswprint (wint_t wc) | ||
236 | { | ||
237 | return (wc >= 0 && wc < 128 | ||
238 | ? wc >= ' ' && wc <= '~' | ||
239 | : 1); | ||
240 | } | ||
241 | # define iswprint iswprint | ||
242 | #endif | ||
243 | #if !defined iswpunct && !HAVE_ISWCNTRL | ||
244 | static inline int | ||
245 | iswpunct (wint_t wc) | ||
246 | { | ||
247 | return (wc >= 0 && wc < 128 | ||
248 | ? wc >= '!' && wc <= '~' | ||
249 | && !((wc >= '0' && wc <= '9') | ||
250 | || ((wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'Z')) | ||
251 | : 1); | ||
252 | } | ||
253 | # define iswpunct iswpunct | ||
254 | #endif | ||
255 | #if !defined iswspace && !HAVE_ISWCNTRL | ||
256 | static inline int | ||
257 | iswspace (wint_t wc) | ||
258 | { | ||
259 | return (wc >= 0 && wc < 128 | ||
260 | ? wc == ' ' || wc == '\t' | ||
261 | || wc == '\n' || wc == '\v' || wc == '\f' || wc == '\r' | ||
262 | : 0); | ||
263 | } | ||
264 | # define iswspace iswspace | ||
265 | #endif | ||
266 | #if !defined iswupper && !HAVE_ISWCNTRL | ||
267 | static inline int | ||
268 | iswupper (wint_t wc) | ||
269 | { | ||
270 | return (wc >= 0 && wc < 128 | ||
271 | ? wc >= 'A' && wc <= 'Z' | ||
272 | : 0); | ||
273 | } | ||
274 | # define iswupper iswupper | ||
275 | #endif | ||
276 | #if !defined iswxdigit && !HAVE_ISWCNTRL | ||
277 | static inline int | ||
278 | iswxdigit (wint_t wc) | ||
279 | { | ||
280 | return (wc >= '0' && wc <= '9') || ((wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'F'); | ||
281 | } | ||
282 | # define iswxdigit iswxdigit | ||
283 | #endif | ||
284 | |||
285 | #include "wcwidth.h" | ||
286 | |||
287 | #define MBCHAR_BUF_SIZE 24 | ||
288 | |||
289 | struct mbchar | ||
290 | { | ||
291 | const char *ptr; /* pointer to current character */ | ||
292 | size_t bytes; /* number of bytes of current character, > 0 */ | ||
293 | bool wc_valid; /* true if wc is a valid wide character */ | ||
294 | wchar_t wc; /* if wc_valid: the current character */ | ||
295 | char buf[MBCHAR_BUF_SIZE]; /* room for the bytes, used for file input only */ | ||
296 | }; | ||
297 | |||
298 | /* EOF (not a real character) is represented with bytes = 0 and | ||
299 | wc_valid = false. */ | ||
300 | |||
301 | typedef struct mbchar mbchar_t; | ||
302 | |||
303 | /* Access the current character. */ | ||
304 | #define mb_ptr(mbc) ((mbc).ptr) | ||
305 | #define mb_len(mbc) ((mbc).bytes) | ||
306 | |||
307 | /* Comparison of characters. */ | ||
308 | #define mb_iseq(mbc, sc) ((mbc).wc_valid && (mbc).wc == (sc)) | ||
309 | #define mb_isnul(mbc) ((mbc).wc_valid && (mbc).wc == 0) | ||
310 | #define mb_cmp(mbc1, mbc2) \ | ||
311 | ((mbc1).wc_valid \ | ||
312 | ? ((mbc2).wc_valid \ | ||
313 | ? (int) (mbc1).wc - (int) (mbc2).wc \ | ||
314 | : -1) \ | ||
315 | : ((mbc2).wc_valid \ | ||
316 | ? 1 \ | ||
317 | : (mbc1).bytes == (mbc2).bytes \ | ||
318 | ? memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) \ | ||
319 | : (mbc1).bytes < (mbc2).bytes \ | ||
320 | ? (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) > 0 ? 1 : -1) \ | ||
321 | : (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc2).bytes) >= 0 ? 1 : -1))) | ||
322 | #define mb_casecmp(mbc1, mbc2) \ | ||
323 | ((mbc1).wc_valid \ | ||
324 | ? ((mbc2).wc_valid \ | ||
325 | ? (int) towlower ((mbc1).wc) - (int) towlower ((mbc2).wc) \ | ||
326 | : -1) \ | ||
327 | : ((mbc2).wc_valid \ | ||
328 | ? 1 \ | ||
329 | : (mbc1).bytes == (mbc2).bytes \ | ||
330 | ? memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) \ | ||
331 | : (mbc1).bytes < (mbc2).bytes \ | ||
332 | ? (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) > 0 ? 1 : -1) \ | ||
333 | : (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc2).bytes) >= 0 ? 1 : -1))) | ||
334 | #define mb_equal(mbc1, mbc2) \ | ||
335 | ((mbc1).wc_valid && (mbc2).wc_valid \ | ||
336 | ? (mbc1).wc == (mbc2).wc \ | ||
337 | : (mbc1).bytes == (mbc2).bytes \ | ||
338 | && memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) == 0) | ||
339 | #define mb_caseequal(mbc1, mbc2) \ | ||
340 | ((mbc1).wc_valid && (mbc2).wc_valid \ | ||
341 | ? towlower ((mbc1).wc) == towlower ((mbc2).wc) \ | ||
342 | : (mbc1).bytes == (mbc2).bytes \ | ||
343 | && memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) == 0) | ||
344 | |||
345 | /* <ctype.h>, <wctype.h> classification. */ | ||
346 | #define mb_isascii(mbc) \ | ||
347 | ((mbc).wc_valid && (mbc).wc >= 0 && (mbc).wc <= 127) | ||
348 | #define mb_isalnum(mbc) ((mbc).wc_valid && iswalnum ((mbc).wc)) | ||
349 | #define mb_isalpha(mbc) ((mbc).wc_valid && iswalpha ((mbc).wc)) | ||
350 | #define mb_isblank(mbc) ((mbc).wc_valid && iswblank ((mbc).wc)) | ||
351 | #define mb_iscntrl(mbc) ((mbc).wc_valid && iswcntrl ((mbc).wc)) | ||
352 | #define mb_isdigit(mbc) ((mbc).wc_valid && iswdigit ((mbc).wc)) | ||
353 | #define mb_isgraph(mbc) ((mbc).wc_valid && iswgraph ((mbc).wc)) | ||
354 | #define mb_islower(mbc) ((mbc).wc_valid && iswlower ((mbc).wc)) | ||
355 | #define mb_isprint(mbc) ((mbc).wc_valid && iswprint ((mbc).wc)) | ||
356 | #define mb_ispunct(mbc) ((mbc).wc_valid && iswpunct ((mbc).wc)) | ||
357 | #define mb_isspace(mbc) ((mbc).wc_valid && iswspace ((mbc).wc)) | ||
358 | #define mb_isupper(mbc) ((mbc).wc_valid && iswupper ((mbc).wc)) | ||
359 | #define mb_isxdigit(mbc) ((mbc).wc_valid && iswxdigit ((mbc).wc)) | ||
360 | |||
361 | /* Extra <wchar.h> function. */ | ||
362 | |||
363 | /* Unprintable characters appear as a small box of width 1. */ | ||
364 | #define MB_UNPRINTABLE_WIDTH 1 | ||
365 | |||
366 | static inline int | ||
367 | mb_width_aux (wint_t wc) | ||
368 | { | ||
369 | int w = wcwidth (wc); | ||
370 | /* For unprintable characters, arbitrarily return 0 for control characters | ||
371 | and MB_UNPRINTABLE_WIDTH otherwise. */ | ||
372 | return (w >= 0 ? w : iswcntrl (wc) ? 0 : MB_UNPRINTABLE_WIDTH); | ||
373 | } | ||
374 | |||
375 | #define mb_width(mbc) \ | ||
376 | ((mbc).wc_valid ? mb_width_aux ((mbc).wc) : MB_UNPRINTABLE_WIDTH) | ||
377 | |||
378 | /* Output. */ | ||
379 | #define mb_putc(mbc, stream) fwrite ((mbc).ptr, 1, (mbc).bytes, (stream)) | ||
380 | |||
381 | /* Assignment. */ | ||
382 | #define mb_setascii(mbc, sc) \ | ||
383 | ((mbc)->ptr = (mbc)->buf, (mbc)->bytes = 1, (mbc)->wc_valid = 1, \ | ||
384 | (mbc)->wc = (mbc)->buf[0] = (sc)) | ||
385 | |||
386 | /* Copying a character. */ | ||
387 | static inline void | ||
388 | mb_copy (mbchar_t *new, const mbchar_t *old) | ||
389 | { | ||
390 | if (old->ptr == &old->buf[0]) | ||
391 | { | ||
392 | memcpy (&new->buf[0], &old->buf[0], old->bytes); | ||
393 | new->ptr = &new->buf[0]; | ||
394 | } | ||
395 | else | ||
396 | new->ptr = old->ptr; | ||
397 | new->bytes = old->bytes; | ||
398 | if ((new->wc_valid = old->wc_valid)) | ||
399 | new->wc = old->wc; | ||
400 | } | ||
401 | |||
402 | |||
403 | /* is_basic(c) tests whether the single-byte character c is in the | ||
404 | ISO C "basic character set". | ||
405 | This is a convenience function, and is in this file only to share code | ||
406 | between mbiter_multi.h and mbfile_multi.h. */ | ||
407 | #if (' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ | ||
408 | && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ | ||
409 | && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ | ||
410 | && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ | ||
411 | && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ | ||
412 | && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ | ||
413 | && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ | ||
414 | && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ | ||
415 | && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ | ||
416 | && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ | ||
417 | && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ | ||
418 | && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ | ||
419 | && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ | ||
420 | && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ | ||
421 | && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ | ||
422 | && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ | ||
423 | && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ | ||
424 | && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ | ||
425 | && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ | ||
426 | && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ | ||
427 | && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ | ||
428 | && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ | ||
429 | && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126) | ||
430 | /* The character set is ISO-646, not EBCDIC. */ | ||
431 | # define IS_BASIC_ASCII 1 | ||
432 | |||
433 | extern unsigned int is_basic_table[]; | ||
434 | |||
435 | static inline bool | ||
436 | is_basic (char c) | ||
437 | { | ||
438 | return (is_basic_table [(unsigned char) c >> 5] >> ((unsigned char) c & 31)) | ||
439 | & 1; | ||
440 | } | ||
441 | |||
442 | #else | ||
443 | |||
444 | static inline bool | ||
445 | is_basic (char c) | ||
446 | { | ||
447 | switch (c) | ||
448 | { | ||
449 | case '\t': case '\v': case '\f': | ||
450 | case ' ': case '!': case '"': case '#': case '%': | ||
451 | case '&': case '\'': case '(': case ')': case '*': | ||
452 | case '+': case ',': case '-': case '.': case '/': | ||
453 | case '0': case '1': case '2': case '3': case '4': | ||
454 | case '5': case '6': case '7': case '8': case '9': | ||
455 | case ':': case ';': case '<': case '=': case '>': | ||
456 | case '?': | ||
457 | case 'A': case 'B': case 'C': case 'D': case 'E': | ||
458 | case 'F': case 'G': case 'H': case 'I': case 'J': | ||
459 | case 'K': case 'L': case 'M': case 'N': case 'O': | ||
460 | case 'P': case 'Q': case 'R': case 'S': case 'T': | ||
461 | case 'U': case 'V': case 'W': case 'X': case 'Y': | ||
462 | case 'Z': | ||
463 | case '[': case '\\': case ']': case '^': case '_': | ||
464 | case 'a': case 'b': case 'c': case 'd': case 'e': | ||
465 | case 'f': case 'g': case 'h': case 'i': case 'j': | ||
466 | case 'k': case 'l': case 'm': case 'n': case 'o': | ||
467 | case 'p': case 'q': case 'r': case 's': case 't': | ||
468 | case 'u': case 'v': case 'w': case 'x': case 'y': | ||
469 | case 'z': case '{': case '|': case '}': case '~': | ||
470 | return 1; | ||
471 | default: | ||
472 | return 0; | ||
473 | } | ||
474 | } | ||
475 | |||
476 | #endif | ||
477 | |||
478 | #endif /* _MBCHAR_H */ |
mailbox/mbuiter.h
deleted
100644 → 0
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 | |||
104 | struct 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 | |||
118 | static inline void | ||
119 | mbuiter_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 | |||
179 | static inline void | ||
180 | mbuiter_multi_reloc (struct mbuiter_multi *iter, ptrdiff_t ptrdiff) | ||
181 | { | ||
182 | iter->cur.ptr += ptrdiff; | ||
183 | } | ||
184 | |||
185 | /* Iteration macros. */ | ||
186 | typedef 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 */ |
mailbox/memchr.c
deleted
100644 → 0
1 | /* Copyright (C) 1991, 1993, 1996, 1997, 1999, 2000, 2003, 2004 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 | |||
10 | NOTE: The canonical source of this file is maintained with the GNU C Library. | ||
11 | Bugs can be reported to bug-glibc@prep.ai.mit.edu. | ||
12 | |||
13 | This program is free software; you can redistribute it and/or modify it | ||
14 | under the terms of the GNU General Public License as published by the | ||
15 | Free Software Foundation; either version 2, or (at your option) any | ||
16 | later version. | ||
17 | |||
18 | This program is distributed in the hope that it will be useful, | ||
19 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | GNU General Public License for more details. | ||
22 | |||
23 | You should have received a copy of the GNU General Public License | ||
24 | along with this program; if not, write to the Free Software Foundation, | ||
25 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ | ||
26 | |||
27 | #ifdef HAVE_CONFIG_H | ||
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. */ | ||
53 | void * | ||
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 | ||
200 | weak_alias (__memchr, BP_SYM (memchr)) | ||
201 | #endif |
mailbox/mempcpy.c
deleted
100644 → 0
1 | /* Copy memory area and return pointer after last written byte. | ||
2 | Copyright (C) 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 | /* Specification. */ | ||
19 | #include "mempcpy.h" | ||
20 | |||
21 | #include <string.h> | ||
22 | |||
23 | /* Copy N bytes of SRC to DEST, return pointer to bytes after the | ||
24 | last written byte. */ | ||
25 | void * | ||
26 | mempcpy (void *dest, const void *src, size_t n) | ||
27 | { | ||
28 | return (char *) memcpy (dest, src, n) + n; | ||
29 | } |
mailbox/mempcpy.h
deleted
100644 → 0
1 | /* Copy memory area and return pointer after last written byte. | ||
2 | Copyright (C) 2003, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ | ||
17 | |||
18 | #ifndef mempcpy | ||
19 | |||
20 | # if HAVE_MEMPCPY | ||
21 | |||
22 | /* Get mempcpy() declaration. */ | ||
23 | # include <string.h> | ||
24 | |||
25 | # else | ||
26 | |||
27 | /* Get size_t */ | ||
28 | # include <stddef.h> | ||
29 | |||
30 | /* Copy N bytes of SRC to DEST, return pointer to bytes after the | ||
31 | last written byte. */ | ||
32 | extern void *mempcpy (void *dest, const void *src, size_t n); | ||
33 | |||
34 | # endif | ||
35 | |||
36 | #endif |
mailbox/minmax.h
deleted
100644 → 0
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 */ |
mailbox/pin.c
deleted
100644 → 0
1 | /* Declaration of program_invocation_name and program_invocation_short_name | ||
2 | for those libc's that don't already have it. These variable are needed | ||
3 | by the argp_ functions. */ | ||
4 | |||
5 | #ifdef HAVE_CONFIG_H | ||
6 | # include <config.h> | ||
7 | #endif | ||
8 | |||
9 | #ifndef HAVE_PROGRAM_INVOCATION_NAME | ||
10 | char *program_invocation_short_name = 0; | ||
11 | char *program_invocation_name = 0; | ||
12 | #endif |
mailbox/printf-args.c
deleted
100644 → 0
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 | #ifdef HAVE_CONFIG_H | ||
19 | # include <config.h> | ||
20 | #endif | ||
21 | |||
22 | /* Specification. */ | ||
23 | #include "printf-args.h" | ||
24 | |||
25 | #ifdef STATIC | ||
26 | STATIC | ||
27 | #endif | ||
28 | int | ||
29 | printf_fetchargs (va_list args, arguments *a) | ||
30 | { | ||
31 | size_t i; | ||
32 | argument *ap; | ||
33 | |||
34 | for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++) | ||
35 | switch (ap->type) | ||
36 | { | ||
37 | case TYPE_SCHAR: | ||
38 | ap->a.a_schar = va_arg (args, /*signed char*/ int); | ||
39 | break; | ||
40 | case TYPE_UCHAR: | ||
41 | ap->a.a_uchar = va_arg (args, /*unsigned char*/ int); | ||
42 | break; | ||
43 | case TYPE_SHORT: | ||
44 | ap->a.a_short = va_arg (args, /*short*/ int); | ||
45 | break; | ||
46 | case TYPE_USHORT: | ||
47 | ap->a.a_ushort = va_arg (args, /*unsigned short*/ int); | ||
48 | break; | ||
49 | case TYPE_INT: | ||
50 | ap->a.a_int = va_arg (args, int); | ||
51 | break; | ||
52 | case TYPE_UINT: | ||
53 | ap->a.a_uint = va_arg (args, unsigned int); | ||
54 | break; | ||
55 | case TYPE_LONGINT: | ||
56 | ap->a.a_longint = va_arg (args, long int); | ||
57 | break; | ||
58 | case TYPE_ULONGINT: | ||
59 | ap->a.a_ulongint = va_arg (args, unsigned long int); | ||
60 | break; | ||
61 | #ifdef HAVE_LONG_LONG | ||
62 | case TYPE_LONGLONGINT: | ||
63 | ap->a.a_longlongint = va_arg (args, long long int); | ||
64 | break; | ||
65 | case TYPE_ULONGLONGINT: | ||
66 | ap->a.a_ulonglongint = va_arg (args, unsigned long long int); | ||
67 | break; | ||
68 | #endif | ||
69 | case TYPE_DOUBLE: | ||
70 | ap->a.a_double = va_arg (args, double); | ||
71 | break; | ||
72 | #ifdef HAVE_LONG_DOUBLE | ||
73 | case TYPE_LONGDOUBLE: | ||
74 | ap->a.a_longdouble = va_arg (args, long double); | ||
75 | break; | ||
76 | #endif | ||
77 | case TYPE_CHAR: | ||
78 | ap->a.a_char = va_arg (args, int); | ||
79 | break; | ||
80 | #ifdef HAVE_WINT_T | ||
81 | case TYPE_WIDE_CHAR: | ||
82 | /* Although ISO C 99 7.24.1.(2) says that wint_t is "unchanged by | ||
83 | default argument promotions", this is not the case in mingw32, | ||
84 | where wint_t is 'unsigned short'. */ | ||
85 | ap->a.a_wide_char = | ||
86 | (sizeof (wint_t) < sizeof (int) | ||
87 | ? va_arg (args, int) | ||
88 | : va_arg (args, wint_t)); | ||
89 | break; | ||
90 | #endif | ||
91 | case TYPE_STRING: | ||
92 | ap->a.a_string = va_arg (args, const char *); | ||
93 | /* A null pointer is an invalid argument for "%s", but in practice | ||
94 | it occurs quite frequently in printf statements that produce | ||
95 | debug output. Use a fallback in this case. */ | ||
96 | if (ap->a.a_string == NULL) | ||
97 | ap->a.a_string = "(NULL)"; | ||
98 | break; | ||
99 | #ifdef HAVE_WCHAR_T | ||
100 | case TYPE_WIDE_STRING: | ||
101 | ap->a.a_wide_string = va_arg (args, const wchar_t *); | ||
102 | /* A null pointer is an invalid argument for "%ls", but in practice | ||
103 | it occurs quite frequently in printf statements that produce | ||
104 | debug output. Use a fallback in this case. */ | ||
105 | if (ap->a.a_wide_string == NULL) | ||
106 | { | ||
107 | static const wchar_t wide_null_string[] = | ||
108 | { | ||
109 | (wchar_t)'(', | ||
110 | (wchar_t)'N', (wchar_t)'U', (wchar_t)'L', (wchar_t)'L', | ||
111 | (wchar_t)')', | ||
112 | (wchar_t)0 | ||
113 | }; | ||
114 | ap->a.a_wide_string = wide_null_string; | ||
115 | } | ||
116 | break; | ||
117 | #endif | ||
118 | case TYPE_POINTER: | ||
119 | ap->a.a_pointer = va_arg (args, void *); | ||
120 | break; | ||
121 | case TYPE_COUNT_SCHAR_POINTER: | ||
122 | ap->a.a_count_schar_pointer = va_arg (args, signed char *); | ||
123 | break; | ||
124 | case TYPE_COUNT_SHORT_POINTER: | ||
125 | ap->a.a_count_short_pointer = va_arg (args, short *); | ||
126 | break; | ||
127 | case TYPE_COUNT_INT_POINTER: | ||
128 | ap->a.a_count_int_pointer = va_arg (args, int *); | ||
129 | break; | ||
130 | case TYPE_COUNT_LONGINT_POINTER: | ||
131 | ap->a.a_count_longint_pointer = va_arg (args, long int *); | ||
132 | break; | ||
133 | #ifdef HAVE_LONG_LONG | ||
134 | case TYPE_COUNT_LONGLONGINT_POINTER: | ||
135 | ap->a.a_count_longlongint_pointer = va_arg (args, long long int *); | ||
136 | break; | ||
137 | #endif | ||
138 | default: | ||
139 | /* Unknown type. */ | ||
140 | return -1; | ||
141 | } | ||
142 | return 0; | ||
143 | } |
mailbox/printf-args.h
deleted
100644 → 0
1 | /* Decomposed printf argument list. | ||
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_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 */ | ||
39 | typedef 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 | ||
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 | ||
72 | , TYPE_COUNT_LONGLONGINT_POINTER | ||
73 | #endif | ||
74 | } arg_type; | ||
75 | |||
76 | /* Polymorphic argument */ | ||
77 | typedef 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 | ||
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 | ||
113 | long long int * a_count_longlongint_pointer; | ||
114 | #endif | ||
115 | } | ||
116 | a; | ||
117 | } | ||
118 | argument; | ||
119 | |||
120 | typedef struct | ||
121 | { | ||
122 | size_t count; | ||
123 | argument *arg; | ||
124 | } | ||
125 | arguments; | ||
126 | |||
127 | |||
128 | /* Fetch the arguments, putting them into a. */ | ||
129 | #ifdef STATIC | ||
130 | STATIC | ||
131 | #else | ||
132 | extern | ||
133 | #endif | ||
134 | int printf_fetchargs (va_list args, arguments *a); | ||
135 | |||
136 | #endif /* _PRINTF_ARGS_H */ |
mailbox/printf-parse.c
deleted
100644 → 0
1 | /* Formatted output to strings. | ||
2 | Copyright (C) 1999-2000, 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 | #ifdef HAVE_CONFIG_H | ||
19 | # include <config.h> | ||
20 | #endif | ||
21 | |||
22 | /* Specification. */ | ||
23 | #if WIDE_CHAR_VERSION | ||
24 | # include "wprintf-parse.h" | ||
25 | #else | ||
26 | # include "printf-parse.h" | ||
27 | #endif | ||
28 | |||
29 | /* Get size_t, NULL. */ | ||
30 | #include <stddef.h> | ||
31 | |||
32 | /* Get intmax_t. */ | ||
33 | #if HAVE_STDINT_H_WITH_UINTMAX | ||
34 | # include <stdint.h> | ||
35 | #endif | ||
36 | #if HAVE_INTTYPES_H_WITH_UINTMAX | ||
37 | # include <inttypes.h> | ||
38 | #endif | ||
39 | |||
40 | /* malloc(), realloc(), free(). */ | ||
41 | #include <stdlib.h> | ||
42 | |||
43 | /* Checked size_t computations. */ | ||
44 | #include "xsize.h" | ||
45 | |||
46 | #if WIDE_CHAR_VERSION | ||
47 | # define PRINTF_PARSE wprintf_parse | ||
48 | # define CHAR_T wchar_t | ||
49 | # define DIRECTIVE wchar_t_directive | ||
50 | # define DIRECTIVES wchar_t_directives | ||
51 | #else | ||
52 | # define PRINTF_PARSE printf_parse | ||
53 | # define CHAR_T char | ||
54 | # define DIRECTIVE char_directive | ||
55 | # define DIRECTIVES char_directives | ||
56 | #endif | ||
57 | |||
58 | #ifdef STATIC | ||
59 | STATIC | ||
60 | #endif | ||
61 | int | ||
62 | PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) | ||
63 | { | ||
64 | const CHAR_T *cp = format; /* pointer into format */ | ||
65 | size_t arg_posn = 0; /* number of regular arguments consumed */ | ||
66 | size_t d_allocated; /* allocated elements of d->dir */ | ||
67 | size_t a_allocated; /* allocated elements of a->arg */ | ||
68 | size_t max_width_length = 0; | ||
69 | size_t max_precision_length = 0; | ||
70 | |||
71 | d->count = 0; | ||
72 | d_allocated = 1; | ||
73 | d->dir = malloc (d_allocated * sizeof (DIRECTIVE)); | ||
74 | if (d->dir == NULL) | ||
75 | /* Out of memory. */ | ||
76 | return -1; | ||
77 | |||
78 | a->count = 0; | ||
79 | a_allocated = 0; | ||
80 | a->arg = NULL; | ||
81 | |||
82 | #define REGISTER_ARG(_index_,_type_) \ | ||
83 | { \ | ||
84 | size_t n = (_index_); \ | ||
85 | if (n >= a_allocated) \ | ||
86 | { \ | ||
87 | size_t memory_size; \ | ||
88 | argument *memory; \ | ||
89 | \ | ||
90 | a_allocated = xtimes (a_allocated, 2); \ | ||
91 | if (a_allocated <= n) \ | ||
92 | a_allocated = xsum (n, 1); \ | ||
93 | memory_size = xtimes (a_allocated, sizeof (argument)); \ | ||
94 | if (size_overflow_p (memory_size)) \ | ||
95 | /* Overflow, would lead to out of memory. */ \ | ||
96 | goto error; \ | ||
97 | memory = (a->arg \ | ||
98 | ? realloc (a->arg, memory_size) \ | ||
99 | : malloc (memory_size)); \ | ||
100 | if (memory == NULL) \ | ||
101 | /* Out of memory. */ \ | ||
102 | goto error; \ | ||
103 | a->arg = memory; \ | ||
104 | } \ | ||
105 | while (a->count <= n) \ | ||
106 | a->arg[a->count++].type = TYPE_NONE; \ | ||
107 | if (a->arg[n].type == TYPE_NONE) \ | ||
108 | a->arg[n].type = (_type_); \ | ||
109 | else if (a->arg[n].type != (_type_)) \ | ||
110 | /* Ambiguous type for positional argument. */ \ | ||
111 | goto error; \ | ||
112 | } | ||
113 | |||
114 | while (*cp != '\0') | ||
115 | { | ||
116 | CHAR_T c = *cp++; | ||
117 | if (c == '%') | ||
118 | { | ||
119 | size_t arg_index = ARG_NONE; | ||
120 | DIRECTIVE *dp = &d->dir[d->count];/* pointer to next directive */ | ||
121 | |||
122 | /* Initialize the next directive. */ | ||
123 | dp->dir_start = cp - 1; | ||
124 | dp->flags = 0; | ||
125 | dp->width_start = NULL; | ||
126 | dp->width_end = NULL; | ||
127 | dp->width_arg_index = ARG_NONE; | ||
128 | dp->precision_start = NULL; | ||
129 | dp->precision_end = NULL; | ||
130 | dp->precision_arg_index = ARG_NONE; | ||
131 | dp->arg_index = ARG_NONE; | ||
132 | |||
133 | /* Test for positional argument. */ | ||
134 | if (*cp >= '0' && *cp <= '9') | ||
135 | { | ||
136 | const CHAR_T *np; | ||
137 | |||
138 | for (np = cp; *np >= '0' && *np <= '9'; np++) | ||
139 | ; | ||
140 | if (*np == '$') | ||
141 | { | ||
142 | size_t n = 0; | ||
143 | |||
144 | for (np = cp; *np >= '0' && *np <= '9'; np++) | ||
145 | n = xsum (xtimes (n, 10), *np - '0'); | ||
146 | if (n == 0) | ||
147 | /* Positional argument 0. */ | ||
148 | goto error; | ||
149 | if (size_overflow_p (n)) | ||
150 | /* n too large, would lead to out of memory later. */ | ||
151 | goto error; | ||
152 | arg_index = n - 1; | ||
153 | cp = np + 1; | ||
154 | } | ||
155 | } | ||
156 | |||
157 | /* Read the flags. */ | ||
158 | for (;;) | ||
159 | { | ||
160 | if (*cp == '\'') | ||
161 | { | ||
162 | dp->flags |= FLAG_GROUP; | ||
163 | cp++; | ||
164 | } | ||
165 | else if (*cp == '-') | ||
166 | { | ||
167 | dp->flags |= FLAG_LEFT; | ||
168 | cp++; | ||
169 | } | ||
170 | else if (*cp == '+') | ||
171 | { | ||
172 | dp->flags |= FLAG_SHOWSIGN; | ||
173 | cp++; | ||
174 | } | ||
175 | else if (*cp == ' ') | ||
176 | { | ||
177 | dp->flags |= FLAG_SPACE; | ||
178 | cp++; | ||
179 | } | ||
180 | else if (*cp == '#') | ||
181 | { | ||
182 | dp->flags |= FLAG_ALT; | ||
183 | cp++; | ||
184 | } | ||
185 | else if (*cp == '0') | ||
186 | { | ||
187 | dp->flags |= FLAG_ZERO; | ||
188 | cp++; | ||
189 | } | ||
190 | else | ||
191 | break; | ||
192 | } | ||
193 | |||
194 | /* Parse the field width. */ | ||
195 | if (*cp == '*') | ||
196 | { | ||
197 | dp->width_start = cp; | ||
198 | cp++; | ||
199 | dp->width_end = cp; | ||
200 | if (max_width_length < 1) | ||
201 | max_width_length = 1; | ||
202 | |||
203 | /* Test for positional argument. */ | ||
204 | if (*cp >= '0' && *cp <= '9') | ||
205 | { | ||
206 | const CHAR_T *np; | ||
207 | |||
208 | for (np = cp; *np >= '0' && *np <= '9'; np++) | ||
209 | ; | ||
210 | if (*np == '$') | ||
211 | { | ||
212 | size_t n = 0; | ||
213 | |||
214 | for (np = cp; *np >= '0' && *np <= '9'; np++) | ||
215 | n = xsum (xtimes (n, 10), *np - '0'); | ||
216 | if (n == 0) | ||
217 | /* Positional argument 0. */ | ||
218 | goto error; | ||
219 | if (size_overflow_p (n)) | ||
220 | /* n too large, would lead to out of memory later. */ | ||
221 | goto error; | ||
222 | dp->width_arg_index = n - 1; | ||
223 | cp = np + 1; | ||
224 | } | ||
225 | } | ||
226 | if (dp->width_arg_index == ARG_NONE) | ||
227 | { | ||
228 | dp->width_arg_index = arg_posn++; | ||
229 | if (dp->width_arg_index == ARG_NONE) | ||
230 | /* arg_posn wrapped around. */ | ||
231 | goto error; | ||
232 | } | ||
233 | REGISTER_ARG (dp->width_arg_index, TYPE_INT); | ||
234 | } | ||
235 | else if (*cp >= '0' && *cp <= '9') | ||
236 | { | ||
237 | size_t width_length; | ||
238 | |||
239 | dp->width_start = cp; | ||
240 | for (; *cp >= '0' && *cp <= '9'; cp++) | ||
241 | ; | ||
242 | dp->width_end = cp; | ||
243 | width_length = dp->width_end - dp->width_start; | ||
244 | if (max_width_length < width_length) | ||
245 | max_width_length = width_length; | ||
246 | } | ||
247 | |||
248 | /* Parse the precision. */ | ||
249 | if (*cp == '.') | ||
250 | { | ||
251 | cp++; | ||
252 | if (*cp == '*') | ||
253 | { | ||
254 | dp->precision_start = cp - 1; | ||
255 | cp++; | ||
256 | dp->precision_end = cp; | ||
257 | if (max_precision_length < 2) | ||
258 | max_precision_length = 2; | ||
259 | |||
260 | /* Test for positional argument. */ | ||
261 | if (*cp >= '0' && *cp <= '9') | ||
262 | { | ||
263 | const CHAR_T *np; | ||
264 | |||
265 | for (np = cp; *np >= '0' && *np <= '9'; np++) | ||
266 | ; | ||
267 | if (*np == '$') | ||
268 | { | ||
269 | size_t n = 0; | ||
270 | |||
271 | for (np = cp; *np >= '0' && *np <= '9'; np++) | ||
272 | n = xsum (xtimes (n, 10), *np - '0'); | ||
273 | if (n == 0) | ||
274 | /* Positional argument 0. */ | ||
275 | goto error; | ||
276 | if (size_overflow_p (n)) | ||
277 | /* n too large, would lead to out of memory | ||
278 | later. */ | ||
279 | goto error; | ||
280 | dp->precision_arg_index = n - 1; | ||
281 | cp = np + 1; | ||
282 | } | ||
283 | } | ||
284 | if (dp->precision_arg_index == ARG_NONE) | ||
285 | { | ||
286 | dp->precision_arg_index = arg_posn++; | ||
287 | if (dp->precision_arg_index == ARG_NONE) | ||
288 | /* arg_posn wrapped around. */ | ||
289 | goto error; | ||
290 | } | ||
291 | REGISTER_ARG (dp->precision_arg_index, TYPE_INT); | ||
292 | } | ||
293 | else | ||
294 | { | ||
295 | size_t precision_length; | ||
296 | |||
297 | dp->precision_start = cp - 1; | ||
298 | for (; *cp >= '0' && *cp <= '9'; cp++) | ||
299 | ; | ||
300 | dp->precision_end = cp; | ||
301 | precision_length = dp->precision_end - dp->precision_start; | ||
302 | if (max_precision_length < precision_length) | ||
303 | max_precision_length = precision_length; | ||
304 | } | ||
305 | } | ||
306 | |||
307 | { | ||
308 | arg_type type; | ||
309 | |||
310 | /* Parse argument type/size specifiers. */ | ||
311 | { | ||
312 | int flags = 0; | ||
313 | |||
314 | for (;;) | ||
315 | { | ||
316 | if (*cp == 'h') | ||
317 | { | ||
318 | flags |= (1 << (flags & 1)); | ||
319 | cp++; | ||
320 | } | ||
321 | else if (*cp == 'L') | ||
322 | { | ||
323 | flags |= 4; | ||
324 | cp++; | ||
325 | } | ||
326 | else if (*cp == 'l') | ||
327 | { | ||
328 | flags += 8; | ||
329 | cp++; | ||
330 | } | ||
331 | #ifdef HAVE_INTMAX_T | ||
332 | else if (*cp == 'j') | ||
333 | { | ||
334 | if (sizeof (intmax_t) > sizeof (long)) | ||
335 | { | ||
336 | /* intmax_t = long long */ | ||
337 | flags += 16; | ||
338 | } | ||
339 | else if (sizeof (intmax_t) > sizeof (int)) | ||
340 | { | ||
341 | /* intmax_t = long */ | ||
342 | flags += 8; | ||
343 | } | ||
344 | cp++; | ||
345 | } | ||
346 | #endif | ||
347 | else if (*cp == 'z' || *cp == 'Z') | ||
348 | { | ||
349 | /* 'z' is standardized in ISO C 99, but glibc uses 'Z' | ||
350 | because the warning facility in gcc-2.95.2 understands | ||
351 | only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */ | ||
352 | if (sizeof (size_t) > sizeof (long)) | ||
353 | { | ||
354 | /* size_t = long long */ | ||
355 | flags += 16; | ||
356 | } | ||
357 | else if (sizeof (size_t) > sizeof (int)) | ||
358 | { | ||
359 | /* size_t = long */ | ||
360 | flags += 8; | ||
361 | } | ||
362 | cp++; | ||
363 | } | ||
364 | else if (*cp == 't') | ||
365 | { | ||
366 | if (sizeof (ptrdiff_t) > sizeof (long)) | ||
367 | { | ||
368 | /* ptrdiff_t = long long */ | ||
369 | flags += 16; | ||
370 | } | ||
371 | else if (sizeof (ptrdiff_t) > sizeof (int)) | ||
372 | { | ||
373 | /* ptrdiff_t = long */ | ||
374 | flags += 8; | ||
375 | } | ||
376 | cp++; | ||
377 | } | ||
378 | else | ||
379 | break; | ||
380 | } | ||
381 | |||
382 | /* Read the conversion character. */ | ||
383 | c = *cp++; | ||
384 | switch (c) | ||
385 | { | ||
386 | case 'd': case 'i': | ||
387 | #ifdef HAVE_LONG_LONG | ||
388 | if (flags >= 16 || (flags & 4)) | ||
389 | type = TYPE_LONGLONGINT; | ||
390 | else | ||
391 | #endif | ||
392 | if (flags >= 8) | ||
393 | type = TYPE_LONGINT; | ||
394 | else if (flags & 2) | ||
395 | type = TYPE_SCHAR; | ||
396 | else if (flags & 1) | ||
397 | type = TYPE_SHORT; | ||
398 | else | ||
399 | type = TYPE_INT; | ||
400 | break; | ||
401 | case 'o': case 'u': case 'x': case 'X': | ||
402 | #ifdef HAVE_LONG_LONG | ||
403 | if (flags >= 16 || (flags & 4)) | ||
404 | type = TYPE_ULONGLONGINT; | ||
405 | else | ||
406 | #endif | ||
407 | if (flags >= 8) | ||
408 | type = TYPE_ULONGINT; | ||
409 | else if (flags & 2) | ||
410 | type = TYPE_UCHAR; | ||
411 | else if (flags & 1) | ||
412 | type = TYPE_USHORT; | ||
413 | else | ||
414 | type = TYPE_UINT; | ||
415 | break; | ||
416 | case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': | ||
417 | case 'a': case 'A': | ||
418 | #ifdef HAVE_LONG_DOUBLE | ||
419 | if (flags >= 16 || (flags & 4)) | ||
420 | type = TYPE_LONGDOUBLE; | ||
421 | else | ||
422 | #endif | ||
423 | type = TYPE_DOUBLE; | ||
424 | break; | ||
425 | case 'c': | ||
426 | if (flags >= 8) | ||
427 | #ifdef HAVE_WINT_T | ||
428 | type = TYPE_WIDE_CHAR; | ||
429 | #else | ||
430 | goto error; | ||
431 | #endif | ||
432 | else | ||
433 | type = TYPE_CHAR; | ||
434 | break; | ||
435 | #ifdef HAVE_WINT_T | ||
436 | case 'C': | ||
437 | type = TYPE_WIDE_CHAR; | ||
438 | c = 'c'; | ||
439 | break; | ||
440 | #endif | ||
441 | case 's': | ||
442 | if (flags >= 8) | ||
443 | #ifdef HAVE_WCHAR_T | ||
444 | type = TYPE_WIDE_STRING; | ||
445 | #else | ||
446 | goto error; | ||
447 | #endif | ||
448 | else | ||
449 | type = TYPE_STRING; | ||
450 | break; | ||
451 | #ifdef HAVE_WCHAR_T | ||
452 | case 'S': | ||
453 | type = TYPE_WIDE_STRING; | ||
454 | c = 's'; | ||
455 | break; | ||
456 | #endif | ||
457 | case 'p': | ||
458 | type = TYPE_POINTER; | ||
459 | break; | ||
460 | case 'n': | ||
461 | #ifdef HAVE_LONG_LONG | ||
462 | if (flags >= 16 || (flags & 4)) | ||
463 | type = TYPE_COUNT_LONGLONGINT_POINTER; | ||
464 | else | ||
465 | #endif | ||
466 | if (flags >= 8) | ||
467 | type = TYPE_COUNT_LONGINT_POINTER; | ||
468 | else if (flags & 2) | ||
469 | type = TYPE_COUNT_SCHAR_POINTER; | ||
470 | else if (flags & 1) | ||
471 | type = TYPE_COUNT_SHORT_POINTER; | ||
472 | else | ||
473 | type = TYPE_COUNT_INT_POINTER; | ||
474 | break; | ||
475 | case '%': | ||
476 | type = TYPE_NONE; | ||
477 | break; | ||
478 | default: | ||
479 | /* Unknown conversion character. */ | ||
480 | goto error; | ||
481 | } | ||
482 | } | ||
483 | |||
484 | if (type != TYPE_NONE) | ||
485 | { | ||
486 | dp->arg_index = arg_index; | ||
487 | if (dp->arg_index == ARG_NONE) | ||
488 | { | ||
489 | dp->arg_index = arg_posn++; | ||
490 | if (dp->arg_index == ARG_NONE) | ||
491 | /* arg_posn wrapped around. */ | ||
492 | goto error; | ||
493 | } | ||
494 | REGISTER_ARG (dp->arg_index, type); | ||
495 | } | ||
496 | dp->conversion = c; | ||
497 | dp->dir_end = cp; | ||
498 | } | ||
499 | |||
500 | d->count++; | ||
501 | if (d->count >= d_allocated) | ||
502 | { | ||
503 | size_t memory_size; | ||
504 | DIRECTIVE *memory; | ||
505 | |||
506 | d_allocated = xtimes (d_allocated, 2); | ||
507 | memory_size = xtimes (d_allocated, sizeof (DIRECTIVE)); | ||
508 | if (size_overflow_p (memory_size)) | ||
509 | /* Overflow, would lead to out of memory. */ | ||
510 | goto error; | ||
511 | memory = realloc (d->dir, memory_size); | ||
512 | if (memory == NULL) | ||
513 | /* Out of memory. */ | ||
514 | goto error; | ||
515 | d->dir = memory; | ||
516 | } | ||
517 | } | ||
518 | } | ||
519 | d->dir[d->count].dir_start = cp; | ||
520 | |||
521 | d->max_width_length = max_width_length; | ||
522 | d->max_precision_length = max_precision_length; | ||
523 | return 0; | ||
524 | |||
525 | error: | ||
526 | if (a->arg) | ||
527 | free (a->arg); | ||
528 | if (d->dir) | ||
529 | free (d->dir); | ||
530 | return -1; | ||
531 | } | ||
532 | |||
533 | #undef DIRECTIVES | ||
534 | #undef DIRECTIVE | ||
535 | #undef CHAR_T | ||
536 | #undef PRINTF_PARSE |
mailbox/printf-parse.h
deleted
100644 → 0
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. */ | ||
36 | typedef 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 | } | ||
50 | char_directive; | ||
51 | |||
52 | /* A parsed format string. */ | ||
53 | typedef struct | ||
54 | { | ||
55 | size_t count; | ||
56 | char_directive *dir; | ||
57 | size_t max_width_length; | ||
58 | size_t max_precision_length; | ||
59 | } | ||
60 | char_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 | ||
68 | STATIC | ||
69 | #else | ||
70 | extern | ||
71 | #endif | ||
72 | int printf_parse (const char *format, char_directives *d, arguments *a); | ||
73 | |||
74 | #endif /* _PRINTF_PARSE_H */ |
mailbox/regcomp.c
deleted
100644 → 0
This diff could not be displayed because it is too large.
mailbox/regex.c
deleted
100644 → 0
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 | #ifdef HAVE_CONFIG_H | ||
21 | # include <config.h> | ||
22 | #endif | ||
23 | |||
24 | /* Make sure noone compiles this code with a C++ compiler. */ | ||
25 | #if defined __cplusplus && defined _LIBC | ||
26 | # error "This is C code, use a C compiler" | ||
27 | #endif | ||
28 | |||
29 | #ifdef _LIBC | ||
30 | /* We have to keep the namespace clean. */ | ||
31 | # define regfree(preg) __regfree (preg) | ||
32 | # define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef) | ||
33 | # define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags) | ||
34 | # define regerror(errcode, preg, errbuf, errbuf_size) \ | ||
35 | __regerror(errcode, preg, errbuf, errbuf_size) | ||
36 | # define re_set_registers(bu, re, nu, st, en) \ | ||
37 | __re_set_registers (bu, re, nu, st, en) | ||
38 | # define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \ | ||
39 | __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) | ||
40 | # define re_match(bufp, string, size, pos, regs) \ | ||
41 | __re_match (bufp, string, size, pos, regs) | ||
42 | # define re_search(bufp, string, size, startpos, range, regs) \ | ||
43 | __re_search (bufp, string, size, startpos, range, regs) | ||
44 | # define re_compile_pattern(pattern, length, bufp) \ | ||
45 | __re_compile_pattern (pattern, length, bufp) | ||
46 | # define re_set_syntax(syntax) __re_set_syntax (syntax) | ||
47 | # define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \ | ||
48 | __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop) | ||
49 | # define re_compile_fastmap(bufp) __re_compile_fastmap (bufp) | ||
50 | |||
51 | # include "../locale/localeinfo.h" | ||
52 | #endif | ||
53 | |||
54 | /* On some systems, limits.h sets RE_DUP_MAX to a lower value than | ||
55 | GNU regex allows. Include it before <regex.h>, which correctly | ||
56 | #undefs RE_DUP_MAX and sets it to the right value. */ | ||
57 | #include <limits.h> | ||
58 | |||
59 | #include <regex.h> | ||
60 | #include "regex_internal.h" | ||
61 | |||
62 | #include "regex_internal.c" | ||
63 | #include "regcomp.c" | ||
64 | #include "regexec.c" | ||
65 | |||
66 | /* Binary backward compatibility. */ | ||
67 | #if _LIBC | ||
68 | # include <shlib-compat.h> | ||
69 | # if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3) | ||
70 | link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.") | ||
71 | int re_max_failures = 2000; | ||
72 | # endif | ||
73 | #endif |
mailbox/regex.h
deleted
100644 → 0
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 | ||
28 | extern "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. */ | ||
56 | typedef 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. */ | ||
61 | typedef size_t __re_idx_t; | ||
62 | |||
63 | /* The type of object sizes. */ | ||
64 | typedef size_t __re_size_t; | ||
65 | |||
66 | /* The type of object sizes, in places where the traditional code | ||
67 | uses unsigned long int. */ | ||
68 | typedef 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 | |||
75 | typedef int regoff_t; | ||
76 | typedef int __re_idx_t; | ||
77 | typedef unsigned int __re_size_t; | ||
78 | typedef 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... */ | ||
86 | typedef long int s_reg_t; | ||
87 | typedef 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. */ | ||
94 | typedef 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. */ | ||
235 | extern 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 | |||
372 | typedef 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 | |||
450 | struct 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 | |||
518 | typedef 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. */ | ||
522 | struct 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. */ | ||
541 | typedef 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. */ | ||
551 | extern 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. */ | ||
556 | extern 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. */ | ||
563 | extern 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). */ | ||
571 | extern 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. */ | ||
579 | extern 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. */ | ||
589 | extern 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'. */ | ||
595 | extern 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. */ | ||
614 | extern 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. */ | ||
622 | extern char *re_comp (const char *); | ||
623 | extern 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. */ | ||
639 | #ifndef __restrict_arr | ||
640 | # if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) \ | ||
641 | && !defined __GNUG__ | ||
642 | # define __restrict_arr __restrict | ||
643 | # else | ||
644 | # define __restrict_arr | ||
645 | # endif | ||
646 | #endif | ||
647 | |||
648 | /* POSIX compatibility. */ | ||
649 | extern int regcomp (regex_t *__restrict __preg, | ||
650 | const char *__restrict __pattern, | ||
651 | int __cflags); | ||
652 | |||
653 | extern int regexec (const regex_t *__restrict __preg, | ||
654 | const char *__restrict __string, size_t __nmatch, | ||
655 | regmatch_t __pmatch[__restrict_arr], | ||
656 | int __eflags); | ||
657 | |||
658 | extern size_t regerror (int __errcode, const regex_t *__restrict __preg, | ||
659 | char *__restrict __errbuf, size_t __errbuf_size); | ||
660 | |||
661 | extern void regfree (regex_t *__preg); | ||
662 | |||
663 | |||
664 | #ifdef __cplusplus | ||
665 | } | ||
666 | #endif /* C++ */ | ||
667 | |||
668 | #endif /* regex.h */ |
mailbox/regex_internal.c
deleted
100644 → 0
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 | |||
20 | static 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; | ||
24 | static re_dfastate_t *create_ci_newstate (const re_dfa_t *dfa, | ||
25 | const re_node_set *nodes, | ||
26 | re_hashval_t hash) internal_function; | ||
27 | static 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 | |||
37 | static reg_errcode_t | ||
38 | internal_function | ||
39 | re_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 | |||
65 | static reg_errcode_t | ||
66 | internal_function | ||
67 | re_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 | |||
128 | static reg_errcode_t | ||
129 | internal_function | ||
130 | re_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 | |||
168 | static void | ||
169 | internal_function | ||
170 | re_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 | |||
200 | static void | ||
201 | internal_function | ||
202 | build_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 | |||
268 | static reg_errcode_t | ||
269 | internal_function | ||
270 | build_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 | |||
484 | static Idx | ||
485 | internal_function | ||
486 | re_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 | |||
526 | static void | ||
527 | internal_function | ||
528 | build_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 | |||
549 | static void | ||
550 | internal_function | ||
551 | re_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 | |||
570 | static reg_errcode_t | ||
571 | internal_function | ||
572 | re_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 | /* Are the characters which are already checked remain? */ | ||
601 | if (BE (offset < pstr->valid_raw_len, 1) | ||
602 | #ifdef RE_ENABLE_I18N | ||
603 | /* Handling this would enlarge the code too much. | ||
604 | Accept a slowdown in that case. */ | ||
605 | && pstr->offsets_needed == 0 | ||
606 | #endif | ||
607 | ) | ||
608 | { | ||
609 | /* Yes, move them to the front of the buffer. */ | ||
610 | pstr->tip_context = re_string_context_at (pstr, offset - 1, eflags); | ||
611 | #ifdef RE_ENABLE_I18N | ||
612 | if (pstr->mb_cur_max > 1) | ||
613 | memmove (pstr->wcs, pstr->wcs + offset, | ||
614 | (pstr->valid_len - offset) * sizeof (wint_t)); | ||
615 | #endif /* RE_ENABLE_I18N */ | ||
616 | if (BE (pstr->mbs_allocated, 0)) | ||
617 | memmove (pstr->mbs, pstr->mbs + offset, | ||
618 | pstr->valid_len - offset); | ||
619 | pstr->valid_len -= offset; | ||
620 | pstr->valid_raw_len -= offset; | ||
621 | #if DEBUG | ||
622 | assert (pstr->valid_len > 0); | ||
623 | #endif | ||
624 | } | ||
625 | else | ||
626 | { | ||
627 | /* No, skip all characters until IDX. */ | ||
628 | #ifdef RE_ENABLE_I18N | ||
629 | if (BE (pstr->offsets_needed, 0)) | ||
630 | { | ||
631 | pstr->len = pstr->raw_len - idx + offset; | ||
632 | pstr->stop = pstr->raw_stop - idx + offset; | ||
633 | pstr->offsets_needed = 0; | ||
634 | } | ||
635 | #endif | ||
636 | pstr->valid_len = 0; | ||
637 | #ifdef RE_ENABLE_I18N | ||
638 | if (pstr->mb_cur_max > 1) | ||
639 | { | ||
640 | Idx wcs_idx; | ||
641 | wint_t wc = WEOF; | ||
642 | |||
643 | if (pstr->is_utf8) | ||
644 | { | ||
645 | const unsigned char *raw, *p, *q, *end; | ||
646 | |||
647 | /* Special case UTF-8. Multi-byte chars start with any | ||
648 | byte other than 0x80 - 0xbf. */ | ||
649 | raw = pstr->raw_mbs + pstr->raw_mbs_idx; | ||
650 | end = raw + (offset - pstr->mb_cur_max); | ||
651 | p = raw + offset - 1; | ||
652 | #ifdef _LIBC | ||
653 | /* We know the wchar_t encoding is UCS4, so for the simple | ||
654 | case, ASCII characters, skip the conversion step. */ | ||
655 | if (isascii (*p) && BE (pstr->trans == NULL, 1)) | ||
656 | { | ||
657 | memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); | ||
658 | pstr->valid_len = 0; | ||
659 | wc = (wchar_t) *p; | ||
660 | } | ||
661 | else | ||
662 | #endif | ||
663 | for (; p >= end; --p) | ||
664 | if ((*p & 0xc0) != 0x80) | ||
665 | { | ||
666 | mbstate_t cur_state; | ||
667 | wchar_t wc2; | ||
668 | Idx mlen = raw + pstr->len - p; | ||
669 | unsigned char buf[6]; | ||
670 | size_t mbclen; | ||
671 | |||
672 | q = p; | ||
673 | if (BE (pstr->trans != NULL, 0)) | ||
674 | { | ||
675 | int i = mlen < 6 ? mlen : 6; | ||
676 | while (--i >= 0) | ||
677 | buf[i] = pstr->trans[p[i]]; | ||
678 | q = buf; | ||
679 | } | ||
680 | /* XXX Don't use mbrtowc, we know which conversion | ||
681 | to use (UTF-8 -> UCS4). */ | ||
682 | memset (&cur_state, 0, sizeof (cur_state)); | ||
683 | mbclen = mbrtowc (&wc2, (const char *) p, mlen, | ||
684 | &cur_state); | ||
685 | if (raw + offset - p <= mbclen | ||
686 | && mbclen < (size_t) -2) | ||
687 | { | ||
688 | memset (&pstr->cur_state, '\0', | ||
689 | sizeof (mbstate_t)); | ||
690 | pstr->valid_len = mbclen - (raw + offset - p); | ||
691 | wc = wc2; | ||
692 | } | ||
693 | break; | ||
694 | } | ||
695 | } | ||
696 | |||
697 | if (wc == WEOF) | ||
698 | pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx; | ||
699 | if (wc == WEOF) | ||
700 | pstr->tip_context | ||
701 | = re_string_context_at (pstr, pstr->valid_raw_len - 1, eflags); | ||
702 | else | ||
703 | pstr->tip_context = ((BE (pstr->word_ops_used != 0, 0) | ||
704 | && IS_WIDE_WORD_CHAR (wc)) | ||
705 | ? CONTEXT_WORD | ||
706 | : ((IS_WIDE_NEWLINE (wc) | ||
707 | && pstr->newline_anchor) | ||
708 | ? CONTEXT_NEWLINE : 0)); | ||
709 | if (BE (pstr->valid_len, 0)) | ||
710 | { | ||
711 | for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx) | ||
712 | pstr->wcs[wcs_idx] = WEOF; | ||
713 | if (pstr->mbs_allocated) | ||
714 | memset (pstr->mbs, -1, pstr->valid_len); | ||
715 | } | ||
716 | pstr->valid_raw_len = pstr->valid_len; | ||
717 | } | ||
718 | else | ||
719 | #endif /* RE_ENABLE_I18N */ | ||
720 | { | ||
721 | int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1]; | ||
722 | pstr->valid_raw_len = 0; | ||
723 | if (pstr->trans) | ||
724 | c = pstr->trans[c]; | ||
725 | pstr->tip_context = (bitset_contain (pstr->word_char, c) | ||
726 | ? CONTEXT_WORD | ||
727 | : ((IS_NEWLINE (c) && pstr->newline_anchor) | ||
728 | ? CONTEXT_NEWLINE : 0)); | ||
729 | } | ||
730 | } | ||
731 | if (!BE (pstr->mbs_allocated, 0)) | ||
732 | pstr->mbs += offset; | ||
733 | } | ||
734 | pstr->raw_mbs_idx = idx; | ||
735 | pstr->len -= offset; | ||
736 | pstr->stop -= offset; | ||
737 | |||
738 | /* Then build the buffers. */ | ||
739 | #ifdef RE_ENABLE_I18N | ||
740 | if (pstr->mb_cur_max > 1) | ||
741 | { | ||
742 | if (pstr->icase) | ||
743 | { | ||
744 | reg_errcode_t ret = build_wcs_upper_buffer (pstr); | ||
745 | if (BE (ret != REG_NOERROR, 0)) | ||
746 | return ret; | ||
747 | } | ||
748 | else | ||
749 | build_wcs_buffer (pstr); | ||
750 | } | ||
751 | else | ||
752 | #endif /* RE_ENABLE_I18N */ | ||
753 | if (BE (pstr->mbs_allocated, 0)) | ||
754 | { | ||
755 | if (pstr->icase) | ||
756 | build_upper_buffer (pstr); | ||
757 | else if (pstr->trans != NULL) | ||
758 | re_string_translate_buffer (pstr); | ||
759 | } | ||
760 | else | ||
761 | pstr->valid_len = pstr->len; | ||
762 | |||
763 | pstr->cur_idx = 0; | ||
764 | return REG_NOERROR; | ||
765 | } | ||
766 | |||
767 | static unsigned char | ||
768 | internal_function __attribute ((pure)) | ||
769 | re_string_peek_byte_case (const re_string_t *pstr, Idx idx) | ||
770 | { | ||
771 | int ch; | ||
772 | Idx off; | ||
773 | |||
774 | /* Handle the common (easiest) cases first. */ | ||
775 | if (BE (!pstr->mbs_allocated, 1)) | ||
776 | return re_string_peek_byte (pstr, idx); | ||
777 | |||
778 | #ifdef RE_ENABLE_I18N | ||
779 | if (pstr->mb_cur_max > 1 | ||
780 | && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx)) | ||
781 | return re_string_peek_byte (pstr, idx); | ||
782 | #endif | ||
783 | |||
784 | off = pstr->cur_idx + idx; | ||
785 | #ifdef RE_ENABLE_I18N | ||
786 | if (pstr->offsets_needed) | ||
787 | off = pstr->offsets[off]; | ||
788 | #endif | ||
789 | |||
790 | ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; | ||
791 | |||
792 | #ifdef RE_ENABLE_I18N | ||
793 | /* Ensure that e.g. for tr_TR.UTF-8 BACKSLASH DOTLESS SMALL LETTER I | ||
794 | this function returns CAPITAL LETTER I instead of first byte of | ||
795 | DOTLESS SMALL LETTER I. The latter would confuse the parser, | ||
796 | since peek_byte_case doesn't advance cur_idx in any way. */ | ||
797 | if (pstr->offsets_needed && !isascii (ch)) | ||
798 | return re_string_peek_byte (pstr, idx); | ||
799 | #endif | ||
800 | |||
801 | return ch; | ||
802 | } | ||
803 | |||
804 | static unsigned char | ||
805 | internal_function __attribute ((pure)) | ||
806 | re_string_fetch_byte_case (re_string_t *pstr) | ||
807 | { | ||
808 | if (BE (!pstr->mbs_allocated, 1)) | ||
809 | return re_string_fetch_byte (pstr); | ||
810 | |||
811 | #ifdef RE_ENABLE_I18N | ||
812 | if (pstr->offsets_needed) | ||
813 | { | ||
814 | Idx off; | ||
815 | int ch; | ||
816 | |||
817 | /* For tr_TR.UTF-8 [[:islower:]] there is | ||
818 | [[: CAPITAL LETTER I WITH DOT lower:]] in mbs. Skip | ||
819 | in that case the whole multi-byte character and return | ||
820 | the original letter. On the other side, with | ||
821 | [[: DOTLESS SMALL LETTER I return [[:I, as doing | ||
822 | anything else would complicate things too much. */ | ||
823 | |||
824 | if (!re_string_first_byte (pstr, pstr->cur_idx)) | ||
825 | return re_string_fetch_byte (pstr); | ||
826 | |||
827 | off = pstr->offsets[pstr->cur_idx]; | ||
828 | ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; | ||
829 | |||
830 | if (! isascii (ch)) | ||
831 | return re_string_fetch_byte (pstr); | ||
832 | |||
833 | re_string_skip_bytes (pstr, | ||
834 | re_string_char_size_at (pstr, pstr->cur_idx)); | ||
835 | return ch; | ||
836 | } | ||
837 | #endif | ||
838 | |||
839 | return pstr->raw_mbs[pstr->raw_mbs_idx + pstr->cur_idx++]; | ||
840 | } | ||
841 | |||
842 | static void | ||
843 | internal_function | ||
844 | re_string_destruct (re_string_t *pstr) | ||
845 | { | ||
846 | #ifdef RE_ENABLE_I18N | ||
847 | re_free (pstr->wcs); | ||
848 | re_free (pstr->offsets); | ||
849 | #endif /* RE_ENABLE_I18N */ | ||
850 | if (pstr->mbs_allocated) | ||
851 | re_free (pstr->mbs); | ||
852 | } | ||
853 | |||
854 | /* Return the context at IDX in INPUT. */ | ||
855 | |||
856 | static unsigned int | ||
857 | internal_function | ||
858 | re_string_context_at (const re_string_t *input, Idx idx, int eflags) | ||
859 | { | ||
860 | int c; | ||
861 | if (BE (! REG_VALID_INDEX (idx), 0)) | ||
862 | /* In this case, we use the value stored in input->tip_context, | ||
863 | since we can't know the character in input->mbs[-1] here. */ | ||
864 | return input->tip_context; | ||
865 | if (BE (idx == input->len, 0)) | ||
866 | return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF | ||
867 | : CONTEXT_NEWLINE | CONTEXT_ENDBUF); | ||
868 | #ifdef RE_ENABLE_I18N | ||
869 | if (input->mb_cur_max > 1) | ||
870 | { | ||
871 | wint_t wc; | ||
872 | Idx wc_idx = idx; | ||
873 | while(input->wcs[wc_idx] == WEOF) | ||
874 | { | ||
875 | #ifdef DEBUG | ||
876 | /* It must not happen. */ | ||
877 | assert (REG_VALID_INDEX (wc_idx)); | ||
878 | #endif | ||
879 | --wc_idx; | ||
880 | if (! REG_VALID_INDEX (wc_idx)) | ||
881 | return input->tip_context; | ||
882 | } | ||
883 | wc = input->wcs[wc_idx]; | ||
884 | if (BE (input->word_ops_used != 0, 0) && IS_WIDE_WORD_CHAR (wc)) | ||
885 | return CONTEXT_WORD; | ||
886 | return (IS_WIDE_NEWLINE (wc) && input->newline_anchor | ||
887 | ? CONTEXT_NEWLINE : 0); | ||
888 | } | ||
889 | else | ||
890 | #endif | ||
891 | { | ||
892 | c = re_string_byte_at (input, idx); | ||
893 | if (bitset_contain (input->word_char, c)) | ||
894 | return CONTEXT_WORD; | ||
895 | return IS_NEWLINE (c) && input->newline_anchor ? CONTEXT_NEWLINE : 0; | ||
896 | } | ||
897 | } | ||
898 | |||
899 | /* Functions for set operation. */ | ||
900 | |||
901 | static reg_errcode_t | ||
902 | internal_function | ||
903 | re_node_set_alloc (re_node_set *set, Idx size) | ||
904 | { | ||
905 | set->alloc = size; | ||
906 | set->nelem = 0; | ||
907 | set->elems = re_malloc (Idx, size); | ||
908 | if (BE (set->elems == NULL, 0)) | ||
909 | return REG_ESPACE; | ||
910 | return REG_NOERROR; | ||
911 | } | ||
912 | |||
913 | static reg_errcode_t | ||
914 | internal_function | ||
915 | re_node_set_init_1 (re_node_set *set, Idx elem) | ||
916 | { | ||
917 | set->alloc = 1; | ||
918 | set->nelem = 1; | ||
919 | set->elems = re_malloc (Idx, 1); | ||
920 | if (BE (set->elems == NULL, 0)) | ||
921 | { | ||
922 | set->alloc = set->nelem = 0; | ||
923 | return REG_ESPACE; | ||
924 | } | ||
925 | set->elems[0] = elem; | ||
926 | return REG_NOERROR; | ||
927 | } | ||
928 | |||
929 | static reg_errcode_t | ||
930 | internal_function | ||
931 | re_node_set_init_2 (re_node_set *set, Idx elem1, Idx elem2) | ||
932 | { | ||
933 | set->alloc = 2; | ||
934 | set->elems = re_malloc (Idx, 2); | ||
935 | if (BE (set->elems == NULL, 0)) | ||
936 | return REG_ESPACE; | ||
937 | if (elem1 == elem2) | ||
938 | { | ||
939 | set->nelem = 1; | ||
940 | set->elems[0] = elem1; | ||
941 | } | ||
942 | else | ||
943 | { | ||
944 | set->nelem = 2; | ||
945 | if (elem1 < elem2) | ||
946 | { | ||
947 | set->elems[0] = elem1; | ||
948 | set->elems[1] = elem2; | ||
949 | } | ||
950 | else | ||
951 | { | ||
952 | set->elems[0] = elem2; | ||
953 | set->elems[1] = elem1; | ||
954 | } | ||
955 | } | ||
956 | return REG_NOERROR; | ||
957 | } | ||
958 | |||
959 | static reg_errcode_t | ||
960 | internal_function | ||
961 | re_node_set_init_copy (re_node_set *dest, const re_node_set *src) | ||
962 | { | ||
963 | dest->nelem = src->nelem; | ||
964 | if (src->nelem > 0) | ||
965 | { | ||
966 | dest->alloc = dest->nelem; | ||
967 | dest->elems = re_malloc (Idx, dest->alloc); | ||
968 | if (BE (dest->elems == NULL, 0)) | ||
969 | { | ||
970 | dest->alloc = dest->nelem = 0; | ||
971 | return REG_ESPACE; | ||
972 | } | ||
973 | memcpy (dest->elems, src->elems, src->nelem * sizeof (Idx)); | ||
974 | } | ||
975 | else | ||
976 | re_node_set_init_empty (dest); | ||
977 | return REG_NOERROR; | ||
978 | } | ||
979 | |||
980 | /* Calculate the intersection of the sets SRC1 and SRC2. And merge it to | ||
981 | DEST. Return value indicate the error code or REG_NOERROR if succeeded. | ||
982 | Note: We assume dest->elems is NULL, when dest->alloc is 0. */ | ||
983 | |||
984 | static reg_errcode_t | ||
985 | internal_function | ||
986 | re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1, | ||
987 | const re_node_set *src2) | ||
988 | { | ||
989 | Idx i1, i2, is, id, delta, sbase; | ||
990 | if (src1->nelem == 0 || src2->nelem == 0) | ||
991 | return REG_NOERROR; | ||
992 | |||
993 | /* We need dest->nelem + 2 * elems_in_intersection; this is a | ||
994 | conservative estimate. */ | ||
995 | if (src1->nelem + src2->nelem + dest->nelem > dest->alloc) | ||
996 | { | ||
997 | Idx new_alloc = src1->nelem + src2->nelem + dest->alloc; | ||
998 | Idx *new_elems = re_realloc (dest->elems, Idx, new_alloc); | ||
999 | if (BE (new_elems == NULL, 0)) | ||
1000 | return REG_ESPACE; | ||
1001 | dest->elems = new_elems; | ||
1002 | dest->alloc = new_alloc; | ||
1003 | } | ||
1004 | |||
1005 | /* Find the items in the intersection of SRC1 and SRC2, and copy | ||
1006 | into the top of DEST those that are not already in DEST itself. */ | ||
1007 | sbase = dest->nelem + src1->nelem + src2->nelem; | ||
1008 | i1 = src1->nelem - 1; | ||
1009 | i2 = src2->nelem - 1; | ||
1010 | id = dest->nelem - 1; | ||
1011 | for (;;) | ||
1012 | { | ||
1013 | if (src1->elems[i1] == src2->elems[i2]) | ||
1014 | { | ||
1015 | /* Try to find the item in DEST. Maybe we could binary search? */ | ||
1016 | while (REG_VALID_INDEX (id) && dest->elems[id] > src1->elems[i1]) | ||
1017 | --id; | ||
1018 | |||
1019 | if (! REG_VALID_INDEX (id) || dest->elems[id] != src1->elems[i1]) | ||
1020 | dest->elems[--sbase] = src1->elems[i1]; | ||
1021 | |||
1022 | if (! REG_VALID_INDEX (--i1) || ! REG_VALID_INDEX (--i2)) | ||
1023 | break; | ||
1024 | } | ||
1025 | |||
1026 | /* Lower the highest of the two items. */ | ||
1027 | else if (src1->elems[i1] < src2->elems[i2]) | ||
1028 | { | ||
1029 | if (! REG_VALID_INDEX (--i2)) | ||
1030 | break; | ||
1031 | } | ||
1032 | else | ||
1033 | { | ||
1034 | if (! REG_VALID_INDEX (--i1)) | ||
1035 | break; | ||
1036 | } | ||
1037 | } | ||
1038 | |||
1039 | id = dest->nelem - 1; | ||
1040 | is = dest->nelem + src1->nelem + src2->nelem - 1; | ||
1041 | delta = is - sbase + 1; | ||
1042 | |||
1043 | /* Now copy. When DELTA becomes zero, the remaining | ||
1044 | DEST elements are already in place; this is more or | ||
1045 | less the same loop that is in re_node_set_merge. */ | ||
1046 | dest->nelem += delta; | ||
1047 | if (delta > 0 && REG_VALID_INDEX (id)) | ||
1048 | for (;;) | ||
1049 | { | ||
1050 | if (dest->elems[is] > dest->elems[id]) | ||
1051 | { | ||
1052 | /* Copy from the top. */ | ||
1053 | dest->elems[id + delta--] = dest->elems[is--]; | ||
1054 | if (delta == 0) | ||
1055 | break; | ||
1056 | } | ||
1057 | else | ||
1058 | { | ||
1059 | /* Slide from the bottom. */ | ||
1060 | dest->elems[id + delta] = dest->elems[id]; | ||
1061 | if (! REG_VALID_INDEX (--id)) | ||
1062 | break; | ||
1063 | } | ||
1064 | } | ||
1065 | |||
1066 | /* Copy remaining SRC elements. */ | ||
1067 | memcpy (dest->elems, dest->elems + sbase, delta * sizeof (Idx)); | ||
1068 | |||
1069 | return REG_NOERROR; | ||
1070 | } | ||
1071 | |||
1072 | /* Calculate the union set of the sets SRC1 and SRC2. And store it to | ||
1073 | DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ | ||
1074 | |||
1075 | static reg_errcode_t | ||
1076 | internal_function | ||
1077 | re_node_set_init_union (re_node_set *dest, const re_node_set *src1, | ||
1078 | const re_node_set *src2) | ||
1079 | { | ||
1080 | Idx i1, i2, id; | ||
1081 | if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0) | ||
1082 | { | ||
1083 | dest->alloc = src1->nelem + src2->nelem; | ||
1084 | dest->elems = re_malloc (Idx, dest->alloc); | ||
1085 | if (BE (dest->elems == NULL, 0)) | ||
1086 | return REG_ESPACE; | ||
1087 | } | ||
1088 | else | ||
1089 | { | ||
1090 | if (src1 != NULL && src1->nelem > 0) | ||
1091 | return re_node_set_init_copy (dest, src1); | ||
1092 | else if (src2 != NULL && src2->nelem > 0) | ||
1093 | return re_node_set_init_copy (dest, src2); | ||
1094 | else | ||
1095 | re_node_set_init_empty (dest); | ||
1096 | return REG_NOERROR; | ||
1097 | } | ||
1098 | for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;) | ||
1099 | { | ||
1100 | if (src1->elems[i1] > src2->elems[i2]) | ||
1101 | { | ||
1102 | dest->elems[id++] = src2->elems[i2++]; | ||
1103 | continue; | ||
1104 | } | ||
1105 | if (src1->elems[i1] == src2->elems[i2]) | ||
1106 | ++i2; | ||
1107 | dest->elems[id++] = src1->elems[i1++]; | ||
1108 | } | ||
1109 | if (i1 < src1->nelem) | ||
1110 | { | ||
1111 | memcpy (dest->elems + id, src1->elems + i1, | ||
1112 | (src1->nelem - i1) * sizeof (Idx)); | ||
1113 | id += src1->nelem - i1; | ||
1114 | } | ||
1115 | else if (i2 < src2->nelem) | ||
1116 | { | ||
1117 | memcpy (dest->elems + id, src2->elems + i2, | ||
1118 | (src2->nelem - i2) * sizeof (Idx)); | ||
1119 | id += src2->nelem - i2; | ||
1120 | } | ||
1121 | dest->nelem = id; | ||
1122 | return REG_NOERROR; | ||
1123 | } | ||
1124 | |||
1125 | /* Calculate the union set of the sets DEST and SRC. And store it to | ||
1126 | DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ | ||
1127 | |||
1128 | static reg_errcode_t | ||
1129 | internal_function | ||
1130 | re_node_set_merge (re_node_set *dest, const re_node_set *src) | ||
1131 | { | ||
1132 | Idx is, id, sbase, delta; | ||
1133 | if (src == NULL || src->nelem == 0) | ||
1134 | return REG_NOERROR; | ||
1135 | if (dest->alloc < 2 * src->nelem + dest->nelem) | ||
1136 | { | ||
1137 | Idx new_alloc = 2 * (src->nelem + dest->alloc); | ||
1138 | Idx *new_buffer = re_realloc (dest->elems, Idx, new_alloc); | ||
1139 | if (BE (new_buffer == NULL, 0)) | ||
1140 | return REG_ESPACE; | ||
1141 | dest->elems = new_buffer; | ||
1142 | dest->alloc = new_alloc; | ||
1143 | } | ||
1144 | |||
1145 | if (BE (dest->nelem == 0, 0)) | ||
1146 | { | ||
1147 | dest->nelem = src->nelem; | ||
1148 | memcpy (dest->elems, src->elems, src->nelem * sizeof (Idx)); | ||
1149 | return REG_NOERROR; | ||
1150 | } | ||
1151 | |||
1152 | /* Copy into the top of DEST the items of SRC that are not | ||
1153 | found in DEST. Maybe we could binary search in DEST? */ | ||
1154 | for (sbase = dest->nelem + 2 * src->nelem, | ||
1155 | is = src->nelem - 1, id = dest->nelem - 1; | ||
1156 | REG_VALID_INDEX (is) && REG_VALID_INDEX (id); ) | ||
1157 | { | ||
1158 | if (dest->elems[id] == src->elems[is]) | ||
1159 | is--, id--; | ||
1160 | else if (dest->elems[id] < src->elems[is]) | ||
1161 | dest->elems[--sbase] = src->elems[is--]; | ||
1162 | else /* if (dest->elems[id] > src->elems[is]) */ | ||
1163 | --id; | ||
1164 | } | ||
1165 | |||
1166 | if (REG_VALID_INDEX (is)) | ||
1167 | { | ||
1168 | /* If DEST is exhausted, the remaining items of SRC must be unique. */ | ||
1169 | sbase -= is + 1; | ||
1170 | memcpy (dest->elems + sbase, src->elems, (is + 1) * sizeof (Idx)); | ||
1171 | } | ||
1172 | |||
1173 | id = dest->nelem - 1; | ||
1174 | is = dest->nelem + 2 * src->nelem - 1; | ||
1175 | delta = is - sbase + 1; | ||
1176 | if (delta == 0) | ||
1177 | return REG_NOERROR; | ||
1178 | |||
1179 | /* Now copy. When DELTA becomes zero, the remaining | ||
1180 | DEST elements are already in place. */ | ||
1181 | dest->nelem += delta; | ||
1182 | for (;;) | ||
1183 | { | ||
1184 | if (dest->elems[is] > dest->elems[id]) | ||
1185 | { | ||
1186 | /* Copy from the top. */ | ||
1187 | dest->elems[id + delta--] = dest->elems[is--]; | ||
1188 | if (delta == 0) | ||
1189 | break; | ||
1190 | } | ||
1191 | else | ||
1192 | { | ||
1193 | /* Slide from the bottom. */ | ||
1194 | dest->elems[id + delta] = dest->elems[id]; | ||
1195 | if (! REG_VALID_INDEX (--id)) | ||
1196 | { | ||
1197 | /* Copy remaining SRC elements. */ | ||
1198 | memcpy (dest->elems, dest->elems + sbase, | ||
1199 | delta * sizeof (Idx)); | ||
1200 | break; | ||
1201 | } | ||
1202 | } | ||
1203 | } | ||
1204 | |||
1205 | return REG_NOERROR; | ||
1206 | } | ||
1207 | |||
1208 | /* Insert the new element ELEM to the re_node_set* SET. | ||
1209 | SET should not already have ELEM. | ||
1210 | Return true if successful. */ | ||
1211 | |||
1212 | static bool | ||
1213 | internal_function | ||
1214 | re_node_set_insert (re_node_set *set, Idx elem) | ||
1215 | { | ||
1216 | Idx idx; | ||
1217 | /* In case the set is empty. */ | ||
1218 | if (set->alloc == 0) | ||
1219 | return BE (re_node_set_init_1 (set, elem) == REG_NOERROR, 1); | ||
1220 | |||
1221 | if (BE (set->nelem, 0) == 0) | ||
1222 | { | ||
1223 | /* We already guaranteed above that set->alloc != 0. */ | ||
1224 | set->elems[0] = elem; | ||
1225 | ++set->nelem; | ||
1226 | return true; | ||
1227 | } | ||
1228 | |||
1229 | /* Realloc if we need. */ | ||
1230 | if (set->alloc == set->nelem) | ||
1231 | { | ||
1232 | Idx *new_elems; | ||
1233 | set->alloc = set->alloc * 2; | ||
1234 | new_elems = re_realloc (set->elems, Idx, set->alloc); | ||
1235 | if (BE (new_elems == NULL, 0)) | ||
1236 | return false; | ||
1237 | set->elems = new_elems; | ||
1238 | } | ||
1239 | |||
1240 | /* Move the elements which follows the new element. Test the | ||
1241 | first element separately to skip a check in the inner loop. */ | ||
1242 | if (elem < set->elems[0]) | ||
1243 | { | ||
1244 | idx = 0; | ||
1245 | for (idx = set->nelem; idx > 0; idx--) | ||
1246 | set->elems[idx] = set->elems[idx - 1]; | ||
1247 | } | ||
1248 | else | ||
1249 | { | ||
1250 | for (idx = set->nelem; set->elems[idx - 1] > elem; idx--) | ||
1251 | set->elems[idx] = set->elems[idx - 1]; | ||
1252 | } | ||
1253 | |||
1254 | /* Insert the new element. */ | ||
1255 | set->elems[idx] = elem; | ||
1256 | ++set->nelem; | ||
1257 | return true; | ||
1258 | } | ||
1259 | |||
1260 | /* Insert the new element ELEM to the re_node_set* SET. | ||
1261 | SET should not already have any element greater than or equal to ELEM. | ||
1262 | Return true if successful. */ | ||
1263 | |||
1264 | static bool | ||
1265 | internal_function | ||
1266 | re_node_set_insert_last (re_node_set *set, Idx elem) | ||
1267 | { | ||
1268 | /* Realloc if we need. */ | ||
1269 | if (set->alloc == set->nelem) | ||
1270 | { | ||
1271 | Idx *new_elems; | ||
1272 | set->alloc = (set->alloc + 1) * 2; | ||
1273 | new_elems = re_realloc (set->elems, Idx, set->alloc); | ||
1274 | if (BE (new_elems == NULL, 0)) | ||
1275 | return false; | ||
1276 | set->elems = new_elems; | ||
1277 | } | ||
1278 | |||
1279 | /* Insert the new element. */ | ||
1280 | set->elems[set->nelem++] = elem; | ||
1281 | return true; | ||
1282 | } | ||
1283 | |||
1284 | /* Compare two node sets SET1 and SET2. | ||
1285 | Return true if SET1 and SET2 are equivalent. */ | ||
1286 | |||
1287 | static bool | ||
1288 | internal_function __attribute ((pure)) | ||
1289 | re_node_set_compare (const re_node_set *set1, const re_node_set *set2) | ||
1290 | { | ||
1291 | Idx i; | ||
1292 | if (set1 == NULL || set2 == NULL || set1->nelem != set2->nelem) | ||
1293 | return false; | ||
1294 | for (i = set1->nelem ; REG_VALID_INDEX (--i) ; ) | ||
1295 | if (set1->elems[i] != set2->elems[i]) | ||
1296 | return false; | ||
1297 | return true; | ||
1298 | } | ||
1299 | |||
1300 | /* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise. */ | ||
1301 | |||
1302 | static Idx | ||
1303 | internal_function __attribute ((pure)) | ||
1304 | re_node_set_contains (const re_node_set *set, Idx elem) | ||
1305 | { | ||
1306 | __re_size_t idx, right, mid; | ||
1307 | if (! REG_VALID_NONZERO_INDEX (set->nelem)) | ||
1308 | return 0; | ||
1309 | |||
1310 | /* Binary search the element. */ | ||
1311 | idx = 0; | ||
1312 | right = set->nelem - 1; | ||
1313 | while (idx < right) | ||
1314 | { | ||
1315 | mid = (idx + right) / 2; | ||
1316 | if (set->elems[mid] < elem) | ||
1317 | idx = mid + 1; | ||
1318 | else | ||
1319 | right = mid; | ||
1320 | } | ||
1321 | return set->elems[idx] == elem ? idx + 1 : 0; | ||
1322 | } | ||
1323 | |||
1324 | static void | ||
1325 | internal_function | ||
1326 | re_node_set_remove_at (re_node_set *set, Idx idx) | ||
1327 | { | ||
1328 | if (idx < 0 || idx >= set->nelem) | ||
1329 | return; | ||
1330 | --set->nelem; | ||
1331 | for (; idx < set->nelem; idx++) | ||
1332 | set->elems[idx] = set->elems[idx + 1]; | ||
1333 | } | ||
1334 | |||
1335 | |||
1336 | /* Add the token TOKEN to dfa->nodes, and return the index of the token. | ||
1337 | Or return REG_MISSING if an error occurred. */ | ||
1338 | |||
1339 | static Idx | ||
1340 | internal_function | ||
1341 | re_dfa_add_node (re_dfa_t *dfa, re_token_t token) | ||
1342 | { | ||
1343 | int type = token.type; | ||
1344 | if (BE (dfa->nodes_len >= dfa->nodes_alloc, 0)) | ||
1345 | { | ||
1346 | size_t new_nodes_alloc = dfa->nodes_alloc * 2; | ||
1347 | Idx *new_nexts, *new_indices; | ||
1348 | re_node_set *new_edests, *new_eclosures; | ||
1349 | re_token_t *new_nodes; | ||
1350 | size_t max_object_size = | ||
1351 | MAX (sizeof (re_token_t), | ||
1352 | MAX (sizeof (re_node_set), | ||
1353 | sizeof (Idx))); | ||
1354 | |||
1355 | /* Avoid overflows. */ | ||
1356 | if (BE (SIZE_MAX / 2 / max_object_size < dfa->nodes_alloc, 0)) | ||
1357 | return REG_MISSING; | ||
1358 | |||
1359 | new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc); | ||
1360 | if (BE (new_nodes == NULL, 0)) | ||
1361 | return REG_MISSING; | ||
1362 | dfa->nodes = new_nodes; | ||
1363 | new_nexts = re_realloc (dfa->nexts, Idx, new_nodes_alloc); | ||
1364 | new_indices = re_realloc (dfa->org_indices, Idx, new_nodes_alloc); | ||
1365 | new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc); | ||
1366 | new_eclosures = re_realloc (dfa->eclosures, re_node_set, new_nodes_alloc); | ||
1367 | if (BE (new_nexts == NULL || new_indices == NULL | ||
1368 | || new_edests == NULL || new_eclosures == NULL, 0)) | ||
1369 | return REG_MISSING; | ||
1370 | dfa->nexts = new_nexts; | ||
1371 | dfa->org_indices = new_indices; | ||
1372 | dfa->edests = new_edests; | ||
1373 | dfa->eclosures = new_eclosures; | ||
1374 | dfa->nodes_alloc = new_nodes_alloc; | ||
1375 | } | ||
1376 | dfa->nodes[dfa->nodes_len] = token; | ||
1377 | dfa->nodes[dfa->nodes_len].constraint = 0; | ||
1378 | #ifdef RE_ENABLE_I18N | ||
1379 | dfa->nodes[dfa->nodes_len].accept_mb = | ||
1380 | (type == OP_PERIOD && dfa->mb_cur_max > 1) || type == COMPLEX_BRACKET; | ||
1381 | #endif | ||
1382 | dfa->nexts[dfa->nodes_len] = REG_MISSING; | ||
1383 | re_node_set_init_empty (dfa->edests + dfa->nodes_len); | ||
1384 | re_node_set_init_empty (dfa->eclosures + dfa->nodes_len); | ||
1385 | return dfa->nodes_len++; | ||
1386 | } | ||
1387 | |||
1388 | static inline re_hashval_t | ||
1389 | internal_function | ||
1390 | calc_state_hash (const re_node_set *nodes, unsigned int context) | ||
1391 | { | ||
1392 | re_hashval_t hash = nodes->nelem + context; | ||
1393 | Idx i; | ||
1394 | for (i = 0 ; i < nodes->nelem ; i++) | ||
1395 | hash += nodes->elems[i]; | ||
1396 | return hash; | ||
1397 | } | ||
1398 | |||
1399 | /* Search for the state whose node_set is equivalent to NODES. | ||
1400 | Return the pointer to the state, if we found it in the DFA. | ||
1401 | Otherwise create the new one and return it. In case of an error | ||
1402 | return NULL and set the error code in ERR. | ||
1403 | Note: - We assume NULL as the invalid state, then it is possible that | ||
1404 | return value is NULL and ERR is REG_NOERROR. | ||
1405 | - We never return non-NULL value in case of any errors, it is for | ||
1406 | optimization. */ | ||
1407 | |||
1408 | static re_dfastate_t * | ||
1409 | internal_function | ||
1410 | re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa, | ||
1411 | const re_node_set *nodes) | ||
1412 | { | ||
1413 | re_hashval_t hash; | ||
1414 | re_dfastate_t *new_state; | ||
1415 | struct re_state_table_entry *spot; | ||
1416 | Idx i; | ||
1417 | #ifdef lint | ||
1418 | /* Suppress bogus uninitialized-variable warnings. */ | ||
1419 | *err = REG_NOERROR; | ||
1420 | #endif | ||
1421 | if (BE (nodes->nelem == 0, 0)) | ||
1422 | { | ||
1423 | *err = REG_NOERROR; | ||
1424 | return NULL; | ||
1425 | } | ||
1426 | hash = calc_state_hash (nodes, 0); | ||
1427 | spot = dfa->state_table + (hash & dfa->state_hash_mask); | ||
1428 | |||
1429 | for (i = 0 ; i < spot->num ; i++) | ||
1430 | { | ||
1431 | re_dfastate_t *state = spot->array[i]; | ||
1432 | if (hash != state->hash) | ||
1433 | continue; | ||
1434 | if (re_node_set_compare (&state->nodes, nodes)) | ||
1435 | return state; | ||
1436 | } | ||
1437 | |||
1438 | /* There are no appropriate state in the dfa, create the new one. */ | ||
1439 | new_state = create_ci_newstate (dfa, nodes, hash); | ||
1440 | if (BE (new_state == NULL, 0)) | ||
1441 | *err = REG_ESPACE; | ||
1442 | |||
1443 | return new_state; | ||
1444 | } | ||
1445 | |||
1446 | /* Search for the state whose node_set is equivalent to NODES and | ||
1447 | whose context is equivalent to CONTEXT. | ||
1448 | Return the pointer to the state, if we found it in the DFA. | ||
1449 | Otherwise create the new one and return it. In case of an error | ||
1450 | return NULL and set the error code in ERR. | ||
1451 | Note: - We assume NULL as the invalid state, then it is possible that | ||
1452 | return value is NULL and ERR is REG_NOERROR. | ||
1453 | - We never return non-NULL value in case of any errors, it is for | ||
1454 | optimization. */ | ||
1455 | |||
1456 | static re_dfastate_t * | ||
1457 | internal_function | ||
1458 | re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa, | ||
1459 | const re_node_set *nodes, unsigned int context) | ||
1460 | { | ||
1461 | re_hashval_t hash; | ||
1462 | re_dfastate_t *new_state; | ||
1463 | struct re_state_table_entry *spot; | ||
1464 | Idx i; | ||
1465 | #ifdef lint | ||
1466 | /* Suppress bogus uninitialized-variable warnings. */ | ||
1467 | *err = REG_NOERROR; | ||
1468 | #endif | ||
1469 | if (nodes->nelem == 0) | ||
1470 | { | ||
1471 | *err = REG_NOERROR; | ||
1472 | return NULL; | ||
1473 | } | ||
1474 | hash = calc_state_hash (nodes, context); | ||
1475 | spot = dfa->state_table + (hash & dfa->state_hash_mask); | ||
1476 | |||
1477 | for (i = 0 ; i < spot->num ; i++) | ||
1478 | { | ||
1479 | re_dfastate_t *state = spot->array[i]; | ||
1480 | if (state->hash == hash | ||
1481 | && state->context == context | ||
1482 | && re_node_set_compare (state->entrance_nodes, nodes)) | ||
1483 | return state; | ||
1484 | } | ||
1485 | /* There are no appropriate state in `dfa', create the new one. */ | ||
1486 | new_state = create_cd_newstate (dfa, nodes, context, hash); | ||
1487 | if (BE (new_state == NULL, 0)) | ||
1488 | *err = REG_ESPACE; | ||
1489 | |||
1490 | return new_state; | ||
1491 | } | ||
1492 | |||
1493 | /* Finish initialization of the new state NEWSTATE, and using its hash value | ||
1494 | HASH put in the appropriate bucket of DFA's state table. Return value | ||
1495 | indicates the error code if failed. */ | ||
1496 | |||
1497 | static reg_errcode_t | ||
1498 | register_state (const re_dfa_t *dfa, re_dfastate_t *newstate, | ||
1499 | re_hashval_t hash) | ||
1500 | { | ||
1501 | struct re_state_table_entry *spot; | ||
1502 | reg_errcode_t err; | ||
1503 | Idx i; | ||
1504 | |||
1505 | newstate->hash = hash; | ||
1506 | err = re_node_set_alloc (&newstate->non_eps_nodes, newstate->nodes.nelem); | ||
1507 | if (BE (err != REG_NOERROR, 0)) | ||
1508 | return REG_ESPACE; | ||
1509 | for (i = 0; i < newstate->nodes.nelem; i++) | ||
1510 | { | ||
1511 | Idx elem = newstate->nodes.elems[i]; | ||
1512 | if (!IS_EPSILON_NODE (dfa->nodes[elem].type)) | ||
1513 | if (BE (! re_node_set_insert_last (&newstate->non_eps_nodes, elem), 0)) | ||
1514 | return REG_ESPACE; | ||
1515 | } | ||
1516 | |||
1517 | spot = dfa->state_table + (hash & dfa->state_hash_mask); | ||
1518 | if (BE (spot->alloc <= spot->num, 0)) | ||
1519 | { | ||
1520 | Idx new_alloc = 2 * spot->num + 2; | ||
1521 | re_dfastate_t **new_array = re_realloc (spot->array, re_dfastate_t *, | ||
1522 | new_alloc); | ||
1523 | if (BE (new_array == NULL, 0)) | ||
1524 | return REG_ESPACE; | ||
1525 | spot->array = new_array; | ||
1526 | spot->alloc = new_alloc; | ||
1527 | } | ||
1528 | spot->array[spot->num++] = newstate; | ||
1529 | return REG_NOERROR; | ||
1530 | } | ||
1531 | |||
1532 | static void | ||
1533 | free_state (re_dfastate_t *state) | ||
1534 | { | ||
1535 | re_node_set_free (&state->non_eps_nodes); | ||
1536 | re_node_set_free (&state->inveclosure); | ||
1537 | if (state->entrance_nodes != &state->nodes) | ||
1538 | { | ||
1539 | re_node_set_free (state->entrance_nodes); | ||
1540 | re_free (state->entrance_nodes); | ||
1541 | } | ||
1542 | re_node_set_free (&state->nodes); | ||
1543 | re_free (state->word_trtable); | ||
1544 | re_free (state->trtable); | ||
1545 | re_free (state); | ||
1546 | } | ||
1547 | |||
1548 | /* Create the new state which is independ of contexts. | ||
1549 | Return the new state if succeeded, otherwise return NULL. */ | ||
1550 | |||
1551 | static re_dfastate_t * | ||
1552 | internal_function | ||
1553 | create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes, | ||
1554 | re_hashval_t hash) | ||
1555 | { | ||
1556 | Idx i; | ||
1557 | reg_errcode_t err; | ||
1558 | re_dfastate_t *newstate; | ||
1559 | |||
1560 | newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1); | ||
1561 | if (BE (newstate == NULL, 0)) | ||
1562 | return NULL; | ||
1563 | err = re_node_set_init_copy (&newstate->nodes, nodes); | ||
1564 | if (BE (err != REG_NOERROR, 0)) | ||
1565 | { | ||
1566 | re_free (newstate); | ||
1567 | return NULL; | ||
1568 | } | ||
1569 | |||
1570 | newstate->entrance_nodes = &newstate->nodes; | ||
1571 | for (i = 0 ; i < nodes->nelem ; i++) | ||
1572 | { | ||
1573 | re_token_t *node = dfa->nodes + nodes->elems[i]; | ||
1574 | re_token_type_t type = node->type; | ||
1575 | if (type == CHARACTER && !node->constraint) | ||
1576 | continue; | ||
1577 | #ifdef RE_ENABLE_I18N | ||
1578 | newstate->accept_mb |= node->accept_mb; | ||
1579 | #endif /* RE_ENABLE_I18N */ | ||
1580 | |||
1581 | /* If the state has the halt node, the state is a halt state. */ | ||
1582 | if (type == END_OF_RE) | ||
1583 | newstate->halt = 1; | ||
1584 | else if (type == OP_BACK_REF) | ||
1585 | newstate->has_backref = 1; | ||
1586 | else if (type == ANCHOR || node->constraint) | ||
1587 | newstate->has_constraint = 1; | ||
1588 | } | ||
1589 | err = register_state (dfa, newstate, hash); | ||
1590 | if (BE (err != REG_NOERROR, 0)) | ||
1591 | { | ||
1592 | free_state (newstate); | ||
1593 | newstate = NULL; | ||
1594 | } | ||
1595 | return newstate; | ||
1596 | } | ||
1597 | |||
1598 | /* Create the new state which is depend on the context CONTEXT. | ||
1599 | Return the new state if succeeded, otherwise return NULL. */ | ||
1600 | |||
1601 | static re_dfastate_t * | ||
1602 | internal_function | ||
1603 | create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes, | ||
1604 | unsigned int context, re_hashval_t hash) | ||
1605 | { | ||
1606 | Idx i, nctx_nodes = 0; | ||
1607 | reg_errcode_t err; | ||
1608 | re_dfastate_t *newstate; | ||
1609 | |||
1610 | newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1); | ||
1611 | if (BE (newstate == NULL, 0)) | ||
1612 | return NULL; | ||
1613 | err = re_node_set_init_copy (&newstate->nodes, nodes); | ||
1614 | if (BE (err != REG_NOERROR, 0)) | ||
1615 | { | ||
1616 | re_free (newstate); | ||
1617 | return NULL; | ||
1618 | } | ||
1619 | |||
1620 | newstate->context = context; | ||
1621 | newstate->entrance_nodes = &newstate->nodes; | ||
1622 | |||
1623 | for (i = 0 ; i < nodes->nelem ; i++) | ||
1624 | { | ||
1625 | unsigned int constraint = 0; | ||
1626 | re_token_t *node = dfa->nodes + nodes->elems[i]; | ||
1627 | re_token_type_t type = node->type; | ||
1628 | if (node->constraint) | ||
1629 | constraint = node->constraint; | ||
1630 | |||
1631 | if (type == CHARACTER && !constraint) | ||
1632 | continue; | ||
1633 | #ifdef RE_ENABLE_I18N | ||
1634 | newstate->accept_mb |= node->accept_mb; | ||
1635 | #endif /* RE_ENABLE_I18N */ | ||
1636 | |||
1637 | /* If the state has the halt node, the state is a halt state. */ | ||
1638 | if (type == END_OF_RE) | ||
1639 | newstate->halt = 1; | ||
1640 | else if (type == OP_BACK_REF) | ||
1641 | newstate->has_backref = 1; | ||
1642 | else if (type == ANCHOR) | ||
1643 | constraint = node->opr.ctx_type; | ||
1644 | |||
1645 | if (constraint) | ||
1646 | { | ||
1647 | if (newstate->entrance_nodes == &newstate->nodes) | ||
1648 | { | ||
1649 | newstate->entrance_nodes = re_malloc (re_node_set, 1); | ||
1650 | if (BE (newstate->entrance_nodes == NULL, 0)) | ||
1651 | { | ||
1652 | free_state (newstate); | ||
1653 | return NULL; | ||
1654 | } | ||
1655 | re_node_set_init_copy (newstate->entrance_nodes, nodes); | ||
1656 | nctx_nodes = 0; | ||
1657 | newstate->has_constraint = 1; | ||
1658 | } | ||
1659 | |||
1660 | if (NOT_SATISFY_PREV_CONSTRAINT (constraint,context)) | ||
1661 | { | ||
1662 | re_node_set_remove_at (&newstate->nodes, i - nctx_nodes); | ||
1663 | ++nctx_nodes; | ||
1664 | } | ||
1665 | } | ||
1666 | } | ||
1667 | err = register_state (dfa, newstate, hash); | ||
1668 | if (BE (err != REG_NOERROR, 0)) | ||
1669 | { | ||
1670 | free_state (newstate); | ||
1671 | newstate = NULL; | ||
1672 | } | ||
1673 | return newstate; | ||
1674 | } |
mailbox/regex_internal.h
deleted
100644 → 0
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 | |||
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 | #if defined HAVE_WCHAR_H || defined _LIBC | ||
41 | # include <wchar.h> | ||
42 | #endif /* HAVE_WCHAR_H || _LIBC */ | ||
43 | #if defined HAVE_WCTYPE_H || defined _LIBC | ||
44 | # include <wctype.h> | ||
45 | #endif /* HAVE_WCTYPE_H || _LIBC */ | ||
46 | #include <stdint.h> | ||
47 | #if defined _LIBC | ||
48 | # include <bits/libc-lock.h> | ||
49 | #else | ||
50 | # define __libc_lock_init(NAME) do { } while (0) | ||
51 | # define __libc_lock_lock(NAME) do { } while (0) | ||
52 | # define __libc_lock_unlock(NAME) do { } while (0) | ||
53 | #endif | ||
54 | |||
55 | /* In case that the system doesn't have isblank(). */ | ||
56 | #if !defined _LIBC && !HAVE_DECL_ISBLANK && !defined isblank | ||
57 | # define isblank(ch) ((ch) == ' ' || (ch) == '\t') | ||
58 | #endif | ||
59 | |||
60 | #ifdef _LIBC | ||
61 | # ifndef _RE_DEFINE_LOCALE_FUNCTIONS | ||
62 | # define _RE_DEFINE_LOCALE_FUNCTIONS 1 | ||
63 | # include <locale/localeinfo.h> | ||
64 | # include <locale/elem-hash.h> | ||
65 | # include <locale/coll-lookup.h> | ||
66 | # endif | ||
67 | #endif | ||
68 | |||
69 | /* This is for other GNU distributions with internationalized messages. */ | ||
70 | #if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC | ||
71 | # include <libintl.h> | ||
72 | # ifdef _LIBC | ||
73 | # undef gettext | ||
74 | # define gettext(msgid) \ | ||
75 | INTUSE(__dcgettext) (_libc_intl_domainname, msgid, LC_MESSAGES) | ||
76 | # endif | ||
77 | #else | ||
78 | # define gettext(msgid) (msgid) | ||
79 | #endif | ||
80 | |||
81 | #ifndef gettext_noop | ||
82 | /* This define is so xgettext can find the internationalizable | ||
83 | strings. */ | ||
84 | # define gettext_noop(String) String | ||
85 | #endif | ||
86 | |||
87 | /* For loser systems without the definition. */ | ||
88 | #ifndef SIZE_MAX | ||
89 | # define SIZE_MAX ((size_t) -1) | ||
90 | #endif | ||
91 | |||
92 | #if (defined MB_CUR_MAX && HAVE_LOCALE_H && HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_WCRTOMB && HAVE_MBRTOWC && HAVE_WCSCOLL) || _LIBC | ||
93 | # define RE_ENABLE_I18N | ||
94 | #endif | ||
95 | |||
96 | #if __GNUC__ >= 3 | ||
97 | # define BE(expr, val) __builtin_expect (expr, val) | ||
98 | #else | ||
99 | # define BE(expr, val) (expr) | ||
100 | # ifdef _LIBC | ||
101 | # define inline | ||
102 | # endif | ||
103 | #endif | ||
104 | |||
105 | /* Number of ASCII characters. */ | ||
106 | #define ASCII_CHARS 0x80 | ||
107 | |||
108 | /* Number of single byte characters. */ | ||
109 | #define SBC_MAX (UCHAR_MAX + 1) | ||
110 | |||
111 | #define COLL_ELEM_LEN_MAX 8 | ||
112 | |||
113 | /* The character which represents newline. */ | ||
114 | #define NEWLINE_CHAR '\n' | ||
115 | #define WIDE_NEWLINE_CHAR L'\n' | ||
116 | |||
117 | /* Rename to standard API for using out of glibc. */ | ||
118 | #ifndef _LIBC | ||
119 | # define __wctype wctype | ||
120 | # define __iswctype iswctype | ||
121 | # define __btowc btowc | ||
122 | # ifndef __mempcpy | ||
123 | # define __mempcpy mempcpy | ||
124 | # endif | ||
125 | # define __wcrtomb wcrtomb | ||
126 | # define __regfree regfree | ||
127 | # define attribute_hidden | ||
128 | #endif /* not _LIBC */ | ||
129 | |||
130 | #if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) | ||
131 | # define __attribute(arg) __attribute__ (arg) | ||
132 | #else | ||
133 | # define __attribute(arg) | ||
134 | #endif | ||
135 | |||
136 | typedef __re_idx_t Idx; | ||
137 | |||
138 | /* Special return value for failure to match. */ | ||
139 | #define REG_MISSING ((Idx) -1) | ||
140 | |||
141 | /* Special return value for internal error. */ | ||
142 | #define REG_ERROR ((Idx) -2) | ||
143 | |||
144 | /* Test whether N is a valid index, and is not one of the above. */ | ||
145 | #ifdef _REGEX_LARGE_OFFSETS | ||
146 | # define REG_VALID_INDEX(n) ((Idx) (n) < REG_ERROR) | ||
147 | #else | ||
148 | # define REG_VALID_INDEX(n) (0 <= (n)) | ||
149 | #endif | ||
150 | |||
151 | /* Test whether N is a valid nonzero index. */ | ||
152 | #ifdef _REGEX_LARGE_OFFSETS | ||
153 | # define REG_VALID_NONZERO_INDEX(n) ((Idx) ((n) - 1) < (Idx) (REG_ERROR - 1)) | ||
154 | #else | ||
155 | # define REG_VALID_NONZERO_INDEX(n) (0 < (n)) | ||
156 | #endif | ||
157 | |||
158 | /* A hash value, suitable for computing hash tables. */ | ||
159 | typedef __re_size_t re_hashval_t; | ||
160 | |||
161 | /* An integer used to represent a set of bits. It must be unsigned, | ||
162 | and must be at least as wide as unsigned int. */ | ||
163 | typedef unsigned long int bitset_word_t; | ||
164 | /* All bits set in a bitset_word_t. */ | ||
165 | #define BITSET_WORD_MAX ULONG_MAX | ||
166 | |||
167 | /* Number of bits in a bitset_word_t. For portability to hosts with | ||
168 | padding bits, do not use '(sizeof (bitset_word_t) * CHAR_BIT)'; | ||
169 | instead, deduce it directly from BITSET_WORD_MAX. Avoid | ||
170 | greater-than-32-bit integers and unconditional shifts by more than | ||
171 | 31 bits, as they're not portable. */ | ||
172 | #if BITSET_WORD_MAX == 0xffffffff | ||
173 | # define BITSET_WORD_BITS 32 | ||
174 | #elif BITSET_WORD_MAX >> 31 >> 5 == 1 | ||
175 | # define BITSET_WORD_BITS 36 | ||
176 | #elif BITSET_WORD_MAX >> 31 >> 16 == 1 | ||
177 | # define BITSET_WORD_BITS 48 | ||
178 | #elif BITSET_WORD_MAX >> 31 >> 28 == 1 | ||
179 | # define BITSET_WORD_BITS 60 | ||
180 | #elif BITSET_WORD_MAX >> 31 >> 31 >> 1 == 1 | ||
181 | # define BITSET_WORD_BITS 64 | ||
182 | #elif BITSET_WORD_MAX >> 31 >> 31 >> 9 == 1 | ||
183 | # define BITSET_WORD_BITS 72 | ||
184 | #elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 3 == 1 | ||
185 | # define BITSET_WORD_BITS 128 | ||
186 | #elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 7 == 1 | ||
187 | # define BITSET_WORD_BITS 256 | ||
188 | #elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 7 > 1 | ||
189 | # define BITSET_WORD_BITS 257 /* any value > SBC_MAX will do here */ | ||
190 | # if BITSET_WORD_BITS <= SBC_MAX | ||
191 | # error "Invalid SBC_MAX" | ||
192 | # endif | ||
193 | #elif BITSET_WORD_MAX == (0xffffffff + 2) * 0xffffffff | ||
194 | /* Work around a bug in 64-bit PGC (before version 6.1-2), where the | ||
195 | preprocessor mishandles large unsigned values as if they were signed. */ | ||
196 | # define BITSET_WORD_BITS 64 | ||
197 | #else | ||
198 | # error "Add case for new bitset_word_t size" | ||
199 | #endif | ||
200 | |||
201 | /* Number of bitset_word_t values in a bitset_t. */ | ||
202 | #define BITSET_WORDS ((SBC_MAX + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS) | ||
203 | |||
204 | typedef bitset_word_t bitset_t[BITSET_WORDS]; | ||
205 | typedef bitset_word_t *re_bitset_ptr_t; | ||
206 | typedef const bitset_word_t *re_const_bitset_ptr_t; | ||
207 | |||
208 | #define PREV_WORD_CONSTRAINT 0x0001 | ||
209 | #define PREV_NOTWORD_CONSTRAINT 0x0002 | ||
210 | #define NEXT_WORD_CONSTRAINT 0x0004 | ||
211 | #define NEXT_NOTWORD_CONSTRAINT 0x0008 | ||
212 | #define PREV_NEWLINE_CONSTRAINT 0x0010 | ||
213 | #define NEXT_NEWLINE_CONSTRAINT 0x0020 | ||
214 | #define PREV_BEGBUF_CONSTRAINT 0x0040 | ||
215 | #define NEXT_ENDBUF_CONSTRAINT 0x0080 | ||
216 | #define WORD_DELIM_CONSTRAINT 0x0100 | ||
217 | #define NOT_WORD_DELIM_CONSTRAINT 0x0200 | ||
218 | |||
219 | typedef enum | ||
220 | { | ||
221 | INSIDE_WORD = PREV_WORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, | ||
222 | WORD_FIRST = PREV_NOTWORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, | ||
223 | WORD_LAST = PREV_WORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, | ||
224 | INSIDE_NOTWORD = PREV_NOTWORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, | ||
225 | LINE_FIRST = PREV_NEWLINE_CONSTRAINT, | ||
226 | LINE_LAST = NEXT_NEWLINE_CONSTRAINT, | ||
227 | BUF_FIRST = PREV_BEGBUF_CONSTRAINT, | ||
228 | BUF_LAST = NEXT_ENDBUF_CONSTRAINT, | ||
229 | WORD_DELIM = WORD_DELIM_CONSTRAINT, | ||
230 | NOT_WORD_DELIM = NOT_WORD_DELIM_CONSTRAINT | ||
231 | } re_context_type; | ||
232 | |||
233 | typedef struct | ||
234 | { | ||
235 | Idx alloc; | ||
236 | Idx nelem; | ||
237 | Idx *elems; | ||
238 | } re_node_set; | ||
239 | |||
240 | typedef enum | ||
241 | { | ||
242 | NON_TYPE = 0, | ||
243 | |||
244 | /* Node type, These are used by token, node, tree. */ | ||
245 | CHARACTER = 1, | ||
246 | END_OF_RE = 2, | ||
247 | SIMPLE_BRACKET = 3, | ||
248 | OP_BACK_REF = 4, | ||
249 | OP_PERIOD = 5, | ||
250 | #ifdef RE_ENABLE_I18N | ||
251 | COMPLEX_BRACKET = 6, | ||
252 | OP_UTF8_PERIOD = 7, | ||
253 | #endif /* RE_ENABLE_I18N */ | ||
254 | |||
255 | /* We define EPSILON_BIT as a macro so that OP_OPEN_SUBEXP is used | ||
256 | when the debugger shows values of this enum type. */ | ||
257 | #define EPSILON_BIT 8 | ||
258 | OP_OPEN_SUBEXP = EPSILON_BIT | 0, | ||
259 | OP_CLOSE_SUBEXP = EPSILON_BIT | 1, | ||
260 | OP_ALT = EPSILON_BIT | 2, | ||
261 | OP_DUP_ASTERISK = EPSILON_BIT | 3, | ||
262 | ANCHOR = EPSILON_BIT | 4, | ||
263 | |||
264 | /* Tree type, these are used only by tree. */ | ||
265 | CONCAT = 16, | ||
266 | SUBEXP = 17, | ||
267 | |||
268 | /* Token type, these are used only by token. */ | ||
269 | OP_DUP_PLUS = 18, | ||
270 | OP_DUP_QUESTION, | ||
271 | OP_OPEN_BRACKET, | ||
272 | OP_CLOSE_BRACKET, | ||
273 | OP_CHARSET_RANGE, | ||
274 | OP_OPEN_DUP_NUM, | ||
275 | OP_CLOSE_DUP_NUM, | ||
276 | OP_NON_MATCH_LIST, | ||
277 | OP_OPEN_COLL_ELEM, | ||
278 | OP_CLOSE_COLL_ELEM, | ||
279 | OP_OPEN_EQUIV_CLASS, | ||
280 | OP_CLOSE_EQUIV_CLASS, | ||
281 | OP_OPEN_CHAR_CLASS, | ||
282 | OP_CLOSE_CHAR_CLASS, | ||
283 | OP_WORD, | ||
284 | OP_NOTWORD, | ||
285 | OP_SPACE, | ||
286 | OP_NOTSPACE, | ||
287 | BACK_SLASH | ||
288 | |||
289 | } re_token_type_t; | ||
290 | |||
291 | #ifdef RE_ENABLE_I18N | ||
292 | typedef struct | ||
293 | { | ||
294 | /* Multibyte characters. */ | ||
295 | wchar_t *mbchars; | ||
296 | |||
297 | /* Collating symbols. */ | ||
298 | # ifdef _LIBC | ||
299 | int32_t *coll_syms; | ||
300 | # endif | ||
301 | |||
302 | /* Equivalence classes. */ | ||
303 | # ifdef _LIBC | ||
304 | int32_t *equiv_classes; | ||
305 | # endif | ||
306 | |||
307 | /* Range expressions. */ | ||
308 | # ifdef _LIBC | ||
309 | uint32_t *range_starts; | ||
310 | uint32_t *range_ends; | ||
311 | # else /* not _LIBC */ | ||
312 | wchar_t *range_starts; | ||
313 | wchar_t *range_ends; | ||
314 | # endif /* not _LIBC */ | ||
315 | |||
316 | /* Character classes. */ | ||
317 | wctype_t *char_classes; | ||
318 | |||
319 | /* If this character set is the non-matching list. */ | ||
320 | unsigned int non_match : 1; | ||
321 | |||
322 | /* # of multibyte characters. */ | ||
323 | Idx nmbchars; | ||
324 | |||
325 | /* # of collating symbols. */ | ||
326 | Idx ncoll_syms; | ||
327 | |||
328 | /* # of equivalence classes. */ | ||
329 | Idx nequiv_classes; | ||
330 | |||
331 | /* # of range expressions. */ | ||
332 | Idx nranges; | ||
333 | |||
334 | /* # of character classes. */ | ||
335 | Idx nchar_classes; | ||
336 | } re_charset_t; | ||
337 | #endif /* RE_ENABLE_I18N */ | ||
338 | |||
339 | typedef struct | ||
340 | { | ||
341 | union | ||
342 | { | ||
343 | unsigned char c; /* for CHARACTER */ | ||
344 | re_bitset_ptr_t sbcset; /* for SIMPLE_BRACKET */ | ||
345 | #ifdef RE_ENABLE_I18N | ||
346 | re_charset_t *mbcset; /* for COMPLEX_BRACKET */ | ||
347 | #endif /* RE_ENABLE_I18N */ | ||
348 | Idx idx; /* for BACK_REF */ | ||
349 | re_context_type ctx_type; /* for ANCHOR */ | ||
350 | } opr; | ||
351 | #if __GNUC__ >= 2 | ||
352 | re_token_type_t type : 8; | ||
353 | #else | ||
354 | re_token_type_t type; | ||
355 | #endif | ||
356 | unsigned int constraint : 10; /* context constraint */ | ||
357 | unsigned int duplicated : 1; | ||
358 | unsigned int opt_subexp : 1; | ||
359 | #ifdef RE_ENABLE_I18N | ||
360 | unsigned int accept_mb : 1; | ||
361 | /* These 2 bits can be moved into the union if needed (e.g. if running out | ||
362 | of bits; move opr.c to opr.c.c and move the flags to opr.c.flags). */ | ||
363 | unsigned int mb_partial : 1; | ||
364 | #endif | ||
365 | unsigned int word_char : 1; | ||
366 | } re_token_t; | ||
367 | |||
368 | #define IS_EPSILON_NODE(type) ((type) & EPSILON_BIT) | ||
369 | |||
370 | struct re_string_t | ||
371 | { | ||
372 | /* Indicate the raw buffer which is the original string passed as an | ||
373 | argument of regexec(), re_search(), etc.. */ | ||
374 | const unsigned char *raw_mbs; | ||
375 | /* Store the multibyte string. In case of "case insensitive mode" like | ||
376 | REG_ICASE, upper cases of the string are stored, otherwise MBS points | ||
377 | the same address that RAW_MBS points. */ | ||
378 | unsigned char *mbs; | ||
379 | #ifdef RE_ENABLE_I18N | ||
380 | /* Store the wide character string which is corresponding to MBS. */ | ||
381 | wint_t *wcs; | ||
382 | Idx *offsets; | ||
383 | mbstate_t cur_state; | ||
384 | #endif | ||
385 | /* Index in RAW_MBS. Each character mbs[i] corresponds to | ||
386 | raw_mbs[raw_mbs_idx + i]. */ | ||
387 | Idx raw_mbs_idx; | ||
388 | /* The length of the valid characters in the buffers. */ | ||
389 | Idx valid_len; | ||
390 | /* The corresponding number of bytes in raw_mbs array. */ | ||
391 | Idx valid_raw_len; | ||
392 | /* The length of the buffers MBS and WCS. */ | ||
393 | Idx bufs_len; | ||
394 | /* The index in MBS, which is updated by re_string_fetch_byte. */ | ||
395 | Idx cur_idx; | ||
396 | /* length of RAW_MBS array. */ | ||
397 | Idx raw_len; | ||
398 | /* This is RAW_LEN - RAW_MBS_IDX + VALID_LEN - VALID_RAW_LEN. */ | ||
399 | Idx len; | ||
400 | /* End of the buffer may be shorter than its length in the cases such | ||
401 | as re_match_2, re_search_2. Then, we use STOP for end of the buffer | ||
402 | instead of LEN. */ | ||
403 | Idx raw_stop; | ||
404 | /* This is RAW_STOP - RAW_MBS_IDX adjusted through OFFSETS. */ | ||
405 | Idx stop; | ||
406 | |||
407 | /* The context of mbs[0]. We store the context independently, since | ||
408 | the context of mbs[0] may be different from raw_mbs[0], which is | ||
409 | the beginning of the input string. */ | ||
410 | unsigned int tip_context; | ||
411 | /* The translation passed as a part of an argument of re_compile_pattern. */ | ||
412 | RE_TRANSLATE_TYPE trans; | ||
413 | /* Copy of re_dfa_t's word_char. */ | ||
414 | re_const_bitset_ptr_t word_char; | ||
415 | /* true if REG_ICASE. */ | ||
416 | unsigned char icase; | ||
417 | unsigned char is_utf8; | ||
418 | unsigned char map_notascii; | ||
419 | unsigned char mbs_allocated; | ||
420 | unsigned char offsets_needed; | ||
421 | unsigned char newline_anchor; | ||
422 | unsigned char word_ops_used; | ||
423 | int mb_cur_max; | ||
424 | }; | ||
425 | typedef struct re_string_t re_string_t; | ||
426 | |||
427 | |||
428 | struct re_dfa_t; | ||
429 | typedef struct re_dfa_t re_dfa_t; | ||
430 | |||
431 | #ifndef _LIBC | ||
432 | # ifdef __i386__ | ||
433 | # define internal_function __attribute ((regparm (3), stdcall)) | ||
434 | # else | ||
435 | # define internal_function | ||
436 | # endif | ||
437 | #endif | ||
438 | |||
439 | static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr, | ||
440 | Idx new_buf_len) | ||
441 | internal_function; | ||
442 | #ifdef RE_ENABLE_I18N | ||
443 | static void build_wcs_buffer (re_string_t *pstr) internal_function; | ||
444 | static reg_errcode_t build_wcs_upper_buffer (re_string_t *pstr) | ||
445 | internal_function; | ||
446 | #endif /* RE_ENABLE_I18N */ | ||
447 | static void build_upper_buffer (re_string_t *pstr) internal_function; | ||
448 | static void re_string_translate_buffer (re_string_t *pstr) internal_function; | ||
449 | static unsigned int re_string_context_at (const re_string_t *input, Idx idx, | ||
450 | int eflags) | ||
451 | internal_function __attribute ((pure)); | ||
452 | #define re_string_peek_byte(pstr, offset) \ | ||
453 | ((pstr)->mbs[(pstr)->cur_idx + offset]) | ||
454 | #define re_string_fetch_byte(pstr) \ | ||
455 | ((pstr)->mbs[(pstr)->cur_idx++]) | ||
456 | #define re_string_first_byte(pstr, idx) \ | ||
457 | ((idx) == (pstr)->valid_len || (pstr)->wcs[idx] != WEOF) | ||
458 | #define re_string_is_single_byte_char(pstr, idx) \ | ||
459 | ((pstr)->wcs[idx] != WEOF && ((pstr)->valid_len == (idx) + 1 \ | ||
460 | || (pstr)->wcs[(idx) + 1] != WEOF)) | ||
461 | #define re_string_eoi(pstr) ((pstr)->stop <= (pstr)->cur_idx) | ||
462 | #define re_string_cur_idx(pstr) ((pstr)->cur_idx) | ||
463 | #define re_string_get_buffer(pstr) ((pstr)->mbs) | ||
464 | #define re_string_length(pstr) ((pstr)->len) | ||
465 | #define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx]) | ||
466 | #define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx)) | ||
467 | #define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx)) | ||
468 | |||
469 | #include <alloca.h> | ||
470 | |||
471 | #ifndef _LIBC | ||
472 | # if HAVE_ALLOCA | ||
473 | /* The OS usually guarantees only one guard page at the bottom of the stack, | ||
474 | and a page size can be as small as 4096 bytes. So we cannot safely | ||
475 | allocate anything larger than 4096 bytes. Also care for the possibility | ||
476 | of a few compiler-allocated temporary stack slots. */ | ||
477 | # define __libc_use_alloca(n) ((n) < 4032) | ||
478 | # else | ||
479 | /* alloca is implemented with malloc, so just use malloc. */ | ||
480 | # define __libc_use_alloca(n) 0 | ||
481 | # endif | ||
482 | #endif | ||
483 | |||
484 | #ifndef MAX | ||
485 | # define MAX(a,b) ((a) < (b) ? (b) : (a)) | ||
486 | #endif | ||
487 | |||
488 | #define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t))) | ||
489 | #define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t))) | ||
490 | #define re_free(p) free (p) | ||
491 | |||
492 | struct bin_tree_t | ||
493 | { | ||
494 | struct bin_tree_t *parent; | ||
495 | struct bin_tree_t *left; | ||
496 | struct bin_tree_t *right; | ||
497 | struct bin_tree_t *first; | ||
498 | struct bin_tree_t *next; | ||
499 | |||
500 | re_token_t token; | ||
501 | |||
502 | /* `node_idx' is the index in dfa->nodes, if `type' == 0. | ||
503 | Otherwise `type' indicate the type of this node. */ | ||
504 | Idx node_idx; | ||
505 | }; | ||
506 | typedef struct bin_tree_t bin_tree_t; | ||
507 | |||
508 | #define BIN_TREE_STORAGE_SIZE \ | ||
509 | ((1024 - sizeof (void *)) / sizeof (bin_tree_t)) | ||
510 | |||
511 | struct bin_tree_storage_t | ||
512 | { | ||
513 | struct bin_tree_storage_t *next; | ||
514 | bin_tree_t data[BIN_TREE_STORAGE_SIZE]; | ||
515 | }; | ||
516 | typedef struct bin_tree_storage_t bin_tree_storage_t; | ||
517 | |||
518 | #define CONTEXT_WORD 1 | ||
519 | #define CONTEXT_NEWLINE (CONTEXT_WORD << 1) | ||
520 | #define CONTEXT_BEGBUF (CONTEXT_NEWLINE << 1) | ||
521 | #define CONTEXT_ENDBUF (CONTEXT_BEGBUF << 1) | ||
522 | |||
523 | #define IS_WORD_CONTEXT(c) ((c) & CONTEXT_WORD) | ||
524 | #define IS_NEWLINE_CONTEXT(c) ((c) & CONTEXT_NEWLINE) | ||
525 | #define IS_BEGBUF_CONTEXT(c) ((c) & CONTEXT_BEGBUF) | ||
526 | #define IS_ENDBUF_CONTEXT(c) ((c) & CONTEXT_ENDBUF) | ||
527 | #define IS_ORDINARY_CONTEXT(c) ((c) == 0) | ||
528 | |||
529 | #define IS_WORD_CHAR(ch) (isalnum (ch) || (ch) == '_') | ||
530 | #define IS_NEWLINE(ch) ((ch) == NEWLINE_CHAR) | ||
531 | #define IS_WIDE_WORD_CHAR(ch) (iswalnum (ch) || (ch) == L'_') | ||
532 | #define IS_WIDE_NEWLINE(ch) ((ch) == WIDE_NEWLINE_CHAR) | ||
533 | |||
534 | #define NOT_SATISFY_PREV_CONSTRAINT(constraint,context) \ | ||
535 | ((((constraint) & PREV_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ | ||
536 | || ((constraint & PREV_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ | ||
537 | || ((constraint & PREV_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context))\ | ||
538 | || ((constraint & PREV_BEGBUF_CONSTRAINT) && !IS_BEGBUF_CONTEXT (context))) | ||
539 | |||
540 | #define NOT_SATISFY_NEXT_CONSTRAINT(constraint,context) \ | ||
541 | ((((constraint) & NEXT_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ | ||
542 | || (((constraint) & NEXT_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ | ||
543 | || (((constraint) & NEXT_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context)) \ | ||
544 | || (((constraint) & NEXT_ENDBUF_CONSTRAINT) && !IS_ENDBUF_CONTEXT (context))) | ||
545 | |||
546 | struct re_dfastate_t | ||
547 | { | ||
548 | re_hashval_t hash; | ||
549 | re_node_set nodes; | ||
550 | re_node_set non_eps_nodes; | ||
551 | re_node_set inveclosure; | ||
552 | re_node_set *entrance_nodes; | ||
553 | struct re_dfastate_t **trtable, **word_trtable; | ||
554 | unsigned int context : 4; | ||
555 | unsigned int halt : 1; | ||
556 | /* If this state can accept `multi byte'. | ||
557 | Note that we refer to multibyte characters, and multi character | ||
558 | collating elements as `multi byte'. */ | ||
559 | unsigned int accept_mb : 1; | ||
560 | /* If this state has backreference node(s). */ | ||
561 | unsigned int has_backref : 1; | ||
562 | unsigned int has_constraint : 1; | ||
563 | }; | ||
564 | typedef struct re_dfastate_t re_dfastate_t; | ||
565 | |||
566 | struct re_state_table_entry | ||
567 | { | ||
568 | Idx num; | ||
569 | Idx alloc; | ||
570 | re_dfastate_t **array; | ||
571 | }; | ||
572 | |||
573 | /* Array type used in re_sub_match_last_t and re_sub_match_top_t. */ | ||
574 | |||
575 | typedef struct | ||
576 | { | ||
577 | Idx next_idx; | ||
578 | Idx alloc; | ||
579 | re_dfastate_t **array; | ||
580 | } state_array_t; | ||
581 | |||
582 | /* Store information about the node NODE whose type is OP_CLOSE_SUBEXP. */ | ||
583 | |||
584 | typedef struct | ||
585 | { | ||
586 | Idx node; | ||
587 | Idx str_idx; /* The position NODE match at. */ | ||
588 | state_array_t path; | ||
589 | } re_sub_match_last_t; | ||
590 | |||
591 | /* Store information about the node NODE whose type is OP_OPEN_SUBEXP. | ||
592 | And information about the node, whose type is OP_CLOSE_SUBEXP, | ||
593 | corresponding to NODE is stored in LASTS. */ | ||
594 | |||
595 | typedef struct | ||
596 | { | ||
597 | Idx str_idx; | ||
598 | Idx node; | ||
599 | state_array_t *path; | ||
600 | Idx alasts; /* Allocation size of LASTS. */ | ||
601 | Idx nlasts; /* The number of LASTS. */ | ||
602 | re_sub_match_last_t **lasts; | ||
603 | } re_sub_match_top_t; | ||
604 | |||
605 | struct re_backref_cache_entry | ||
606 | { | ||
607 | Idx node; | ||
608 | Idx str_idx; | ||
609 | Idx subexp_from; | ||
610 | Idx subexp_to; | ||
611 | char more; | ||
612 | char unused; | ||
613 | unsigned short int eps_reachable_subexps_map; | ||
614 | }; | ||
615 | |||
616 | typedef struct | ||
617 | { | ||
618 | /* The string object corresponding to the input string. */ | ||
619 | re_string_t input; | ||
620 | #if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) | ||
621 | const re_dfa_t *const dfa; | ||
622 | #else | ||
623 | const re_dfa_t *dfa; | ||
624 | #endif | ||
625 | /* EFLAGS of the argument of regexec. */ | ||
626 | int eflags; | ||
627 | /* Where the matching ends. */ | ||
628 | Idx match_last; | ||
629 | Idx last_node; | ||
630 | /* The state log used by the matcher. */ | ||
631 | re_dfastate_t **state_log; | ||
632 | Idx state_log_top; | ||
633 | /* Back reference cache. */ | ||
634 | Idx nbkref_ents; | ||
635 | Idx abkref_ents; | ||
636 | struct re_backref_cache_entry *bkref_ents; | ||
637 | int max_mb_elem_len; | ||
638 | Idx nsub_tops; | ||
639 | Idx asub_tops; | ||
640 | re_sub_match_top_t **sub_tops; | ||
641 | } re_match_context_t; | ||
642 | |||
643 | typedef struct | ||
644 | { | ||
645 | re_dfastate_t **sifted_states; | ||
646 | re_dfastate_t **limited_states; | ||
647 | Idx last_node; | ||
648 | Idx last_str_idx; | ||
649 | re_node_set limits; | ||
650 | } re_sift_context_t; | ||
651 | |||
652 | struct re_fail_stack_ent_t | ||
653 | { | ||
654 | Idx idx; | ||
655 | Idx node; | ||
656 | regmatch_t *regs; | ||
657 | re_node_set eps_via_nodes; | ||
658 | }; | ||
659 | |||
660 | struct re_fail_stack_t | ||
661 | { | ||
662 | Idx num; | ||
663 | Idx alloc; | ||
664 | struct re_fail_stack_ent_t *stack; | ||
665 | }; | ||
666 | |||
667 | struct re_dfa_t | ||
668 | { | ||
669 | re_token_t *nodes; | ||
670 | size_t nodes_alloc; | ||
671 | size_t nodes_len; | ||
672 | Idx *nexts; | ||
673 | Idx *org_indices; | ||
674 | re_node_set *edests; | ||
675 | re_node_set *eclosures; | ||
676 | re_node_set *inveclosures; | ||
677 | struct re_state_table_entry *state_table; | ||
678 | re_dfastate_t *init_state; | ||
679 | re_dfastate_t *init_state_word; | ||
680 | re_dfastate_t *init_state_nl; | ||
681 | re_dfastate_t *init_state_begbuf; | ||
682 | bin_tree_t *str_tree; | ||
683 | bin_tree_storage_t *str_tree_storage; | ||
684 | re_bitset_ptr_t sb_char; | ||
685 | int str_tree_storage_idx; | ||
686 | |||
687 | /* number of subexpressions `re_nsub' is in regex_t. */ | ||
688 | re_hashval_t state_hash_mask; | ||
689 | Idx init_node; | ||
690 | Idx nbackref; /* The number of backreference in this dfa. */ | ||
691 | |||
692 | /* Bitmap expressing which backreference is used. */ | ||
693 | bitset_word_t used_bkref_map; | ||
694 | bitset_word_t completed_bkref_map; | ||
695 | |||
696 | unsigned int has_plural_match : 1; | ||
697 | /* If this dfa has "multibyte node", which is a backreference or | ||
698 | a node which can accept multibyte character or multi character | ||
699 | collating element. */ | ||
700 | unsigned int has_mb_node : 1; | ||
701 | unsigned int is_utf8 : 1; | ||
702 | unsigned int map_notascii : 1; | ||
703 | unsigned int word_ops_used : 1; | ||
704 | int mb_cur_max; | ||
705 | bitset_t word_char; | ||
706 | reg_syntax_t syntax; | ||
707 | Idx *subexp_map; | ||
708 | #ifdef DEBUG | ||
709 | char* re_str; | ||
710 | #endif | ||
711 | #ifdef _LIBC | ||
712 | __libc_lock_define (, lock) | ||
713 | #endif | ||
714 | }; | ||
715 | |||
716 | #define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set)) | ||
717 | #define re_node_set_remove(set,id) \ | ||
718 | (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1)) | ||
719 | #define re_node_set_empty(p) ((p)->nelem = 0) | ||
720 | #define re_node_set_free(set) re_free ((set)->elems) | ||
721 | |||
722 | |||
723 | typedef enum | ||
724 | { | ||
725 | SB_CHAR, | ||
726 | MB_CHAR, | ||
727 | EQUIV_CLASS, | ||
728 | COLL_SYM, | ||
729 | CHAR_CLASS | ||
730 | } bracket_elem_type; | ||
731 | |||
732 | typedef struct | ||
733 | { | ||
734 | bracket_elem_type type; | ||
735 | union | ||
736 | { | ||
737 | unsigned char ch; | ||
738 | unsigned char *name; | ||
739 | wchar_t wch; | ||
740 | } opr; | ||
741 | } bracket_elem_t; | ||
742 | |||
743 | |||
744 | /* Inline functions for bitset_t operation. */ | ||
745 | |||
746 | static inline void | ||
747 | bitset_set (bitset_t set, Idx i) | ||
748 | { | ||
749 | set[i / BITSET_WORD_BITS] |= (bitset_word_t) 1 << i % BITSET_WORD_BITS; | ||
750 | } | ||
751 | |||
752 | static inline void | ||
753 | bitset_clear (bitset_t set, Idx i) | ||
754 | { | ||
755 | set[i / BITSET_WORD_BITS] &= ~ ((bitset_word_t) 1 << i % BITSET_WORD_BITS); | ||
756 | } | ||
757 | |||
758 | static inline bool | ||
759 | bitset_contain (const bitset_t set, Idx i) | ||
760 | { | ||
761 | return (set[i / BITSET_WORD_BITS] >> i % BITSET_WORD_BITS) & 1; | ||
762 | } | ||
763 | |||
764 | static inline void | ||
765 | bitset_empty (bitset_t set) | ||
766 | { | ||
767 | memset (set, '\0', sizeof (bitset_t)); | ||
768 | } | ||
769 | |||
770 | static inline void | ||
771 | bitset_set_all (bitset_t set) | ||
772 | { | ||
773 | memset (set, -1, sizeof (bitset_word_t) * (SBC_MAX / BITSET_WORD_BITS)); | ||
774 | if (SBC_MAX % BITSET_WORD_BITS != 0) | ||
775 | set[BITSET_WORDS - 1] = | ||
776 | ((bitset_word_t) 1 << SBC_MAX % BITSET_WORD_BITS) - 1; | ||
777 | } | ||
778 | |||
779 | static inline void | ||
780 | bitset_copy (bitset_t dest, const bitset_t src) | ||
781 | { | ||
782 | memcpy (dest, src, sizeof (bitset_t)); | ||
783 | } | ||
784 | |||
785 | static inline void | ||
786 | bitset_not (bitset_t set) | ||
787 | { | ||
788 | int bitset_i; | ||
789 | for (bitset_i = 0; bitset_i < SBC_MAX / BITSET_WORD_BITS; ++bitset_i) | ||
790 | set[bitset_i] = ~set[bitset_i]; | ||
791 | if (SBC_MAX % BITSET_WORD_BITS != 0) | ||
792 | set[BITSET_WORDS - 1] = | ||
793 | ((((bitset_word_t) 1 << SBC_MAX % BITSET_WORD_BITS) - 1) | ||
794 | & ~set[BITSET_WORDS - 1]); | ||
795 | } | ||
796 | |||
797 | static inline void | ||
798 | bitset_merge (bitset_t dest, const bitset_t src) | ||
799 | { | ||
800 | int bitset_i; | ||
801 | for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) | ||
802 | dest[bitset_i] |= src[bitset_i]; | ||
803 | } | ||
804 | |||
805 | static inline void | ||
806 | bitset_mask (bitset_t dest, const bitset_t src) | ||
807 | { | ||
808 | int bitset_i; | ||
809 | for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) | ||
810 | dest[bitset_i] &= src[bitset_i]; | ||
811 | } | ||
812 | |||
813 | #ifdef RE_ENABLE_I18N | ||
814 | /* Inline functions for re_string. */ | ||
815 | static inline int | ||
816 | internal_function __attribute ((pure)) | ||
817 | re_string_char_size_at (const re_string_t *pstr, Idx idx) | ||
818 | { | ||
819 | int byte_idx; | ||
820 | if (pstr->mb_cur_max == 1) | ||
821 | return 1; | ||
822 | for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx) | ||
823 | if (pstr->wcs[idx + byte_idx] != WEOF) | ||
824 | break; | ||
825 | return byte_idx; | ||
826 | } | ||
827 | |||
828 | static inline wint_t | ||
829 | internal_function __attribute ((pure)) | ||
830 | re_string_wchar_at (const re_string_t *pstr, Idx idx) | ||
831 | { | ||
832 | if (pstr->mb_cur_max == 1) | ||
833 | return (wint_t) pstr->mbs[idx]; | ||
834 | return (wint_t) pstr->wcs[idx]; | ||
835 | } | ||
836 | |||
837 | static int | ||
838 | internal_function __attribute ((pure)) | ||
839 | re_string_elem_size_at (const re_string_t *pstr, Idx idx) | ||
840 | { | ||
841 | # ifdef _LIBC | ||
842 | const unsigned char *p, *extra; | ||
843 | const int32_t *table, *indirect; | ||
844 | int32_t tmp; | ||
845 | # include <locale/weight.h> | ||
846 | uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); | ||
847 | |||
848 | if (nrules != 0) | ||
849 | { | ||
850 | table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); | ||
851 | extra = (const unsigned char *) | ||
852 | _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); | ||
853 | indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, | ||
854 | _NL_COLLATE_INDIRECTMB); | ||
855 | p = pstr->mbs + idx; | ||
856 | tmp = findidx (&p); | ||
857 | return p - pstr->mbs - idx; | ||
858 | } | ||
859 | else | ||
860 | # endif /* _LIBC */ | ||
861 | return 1; | ||
862 | } | ||
863 | #endif /* RE_ENABLE_I18N */ | ||
864 | |||
865 | #endif /* _REGEX_INTERNAL_H */ |
mailbox/regexec.c
deleted
100644 → 0
This diff could not be displayed because it is too large.
mailbox/stat-macros.h
deleted
100644 → 0
1 | /* stat-related macros | ||
2 | |||
3 | Copyright (C) 1993, 1994, 2001, 2002, 2004, 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 | /* Written by Paul Eggert and Jim Meyering. */ | ||
21 | |||
22 | #ifndef STAT_MACROS_H | ||
23 | # define STAT_MACROS_H 1 | ||
24 | |||
25 | # if ! defined S_ISREG && ! defined S_IFREG | ||
26 | # error "you must include <sys/stat.h> before including this file" | ||
27 | # endif | ||
28 | |||
29 | # ifndef S_IFMT | ||
30 | # define S_IFMT 0170000 | ||
31 | # endif | ||
32 | |||
33 | # if STAT_MACROS_BROKEN | ||
34 | # undef S_ISBLK | ||
35 | # undef S_ISCHR | ||
36 | # undef S_ISDIR | ||
37 | # undef S_ISFIFO | ||
38 | # undef S_ISLNK | ||
39 | # undef S_ISNAM | ||
40 | # undef S_ISMPB | ||
41 | # undef S_ISMPC | ||
42 | # undef S_ISNWK | ||
43 | # undef S_ISREG | ||
44 | # undef S_ISSOCK | ||
45 | # endif | ||
46 | |||
47 | |||
48 | # ifndef S_ISBLK | ||
49 | # ifdef S_IFBLK | ||
50 | # define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) | ||
51 | # else | ||
52 | # define S_ISBLK(m) 0 | ||
53 | # endif | ||
54 | # endif | ||
55 | |||
56 | # ifndef S_ISCHR | ||
57 | # ifdef S_IFCHR | ||
58 | # define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) | ||
59 | # else | ||
60 | # define S_ISCHR(m) 0 | ||
61 | # endif | ||
62 | # endif | ||
63 | |||
64 | # ifndef S_ISDIR | ||
65 | # ifdef S_IFDIR | ||
66 | # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) | ||
67 | # else | ||
68 | # define S_ISDIR(m) 0 | ||
69 | # endif | ||
70 | # endif | ||
71 | |||
72 | # ifndef S_ISDOOR /* Solaris 2.5 and up */ | ||
73 | # define S_ISDOOR(m) 0 | ||
74 | # endif | ||
75 | |||
76 | # ifndef S_ISFIFO | ||
77 | # ifdef S_IFIFO | ||
78 | # define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) | ||
79 | # else | ||
80 | # define S_ISFIFO(m) 0 | ||
81 | # endif | ||
82 | # endif | ||
83 | |||
84 | # ifndef S_ISLNK | ||
85 | # ifdef S_IFLNK | ||
86 | # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) | ||
87 | # else | ||
88 | # define S_ISLNK(m) 0 | ||
89 | # endif | ||
90 | # endif | ||
91 | |||
92 | # ifndef S_ISMPB /* V7 */ | ||
93 | # ifdef S_IFMPB | ||
94 | # define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB) | ||
95 | # define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC) | ||
96 | # else | ||
97 | # define S_ISMPB(m) 0 | ||
98 | # define S_ISMPC(m) 0 | ||
99 | # endif | ||
100 | # endif | ||
101 | |||
102 | # ifndef S_ISNAM /* Xenix */ | ||
103 | # ifdef S_IFNAM | ||
104 | # define S_ISNAM(m) (((m) & S_IFMT) == S_IFNAM) | ||
105 | # else | ||
106 | # define S_ISNAM(m) 0 | ||
107 | # endif | ||
108 | # endif | ||
109 | |||
110 | # ifndef S_ISNWK /* HP/UX */ | ||
111 | # ifdef S_IFNWK | ||
112 | # define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK) | ||
113 | # else | ||
114 | # define S_ISNWK(m) 0 | ||
115 | # endif | ||
116 | # endif | ||
117 | |||
118 | # ifndef S_ISPORT /* Solaris 10 and up */ | ||
119 | # define S_ISPORT(m) 0 | ||
120 | # endif | ||
121 | |||
122 | # ifndef S_ISREG | ||
123 | # ifdef S_IFREG | ||
124 | # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) | ||
125 | # else | ||
126 | # define S_ISREG(m) 0 | ||
127 | # endif | ||
128 | # endif | ||
129 | |||
130 | # ifndef S_ISSOCK | ||
131 | # ifdef S_IFSOCK | ||
132 | # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) | ||
133 | # else | ||
134 | # define S_ISSOCK(m) 0 | ||
135 | # endif | ||
136 | # endif | ||
137 | |||
138 | |||
139 | # ifndef S_TYPEISMQ | ||
140 | # define S_TYPEISMQ(p) 0 | ||
141 | # endif | ||
142 | |||
143 | # ifndef S_TYPEISTMO | ||
144 | # define S_TYPEISTMO(p) 0 | ||
145 | # endif | ||
146 | |||
147 | |||
148 | # ifndef S_TYPEISSEM | ||
149 | # ifdef S_INSEM | ||
150 | # define S_TYPEISSEM(p) (S_ISNAM ((p)->st_mode) && (p)->st_rdev == S_INSEM) | ||
151 | # else | ||
152 | # define S_TYPEISSEM(p) 0 | ||
153 | # endif | ||
154 | # endif | ||
155 | |||
156 | # ifndef S_TYPEISSHM | ||
157 | # ifdef S_INSHD | ||
158 | # define S_TYPEISSHM(p) (S_ISNAM ((p)->st_mode) && (p)->st_rdev == S_INSHD) | ||
159 | # else | ||
160 | # define S_TYPEISSHM(p) 0 | ||
161 | # endif | ||
162 | # endif | ||
163 | |||
164 | /* high performance ("contiguous data") */ | ||
165 | # ifndef S_ISCTG | ||
166 | # define S_ISCTG(p) 0 | ||
167 | # endif | ||
168 | |||
169 | /* Cray DMF (data migration facility): off line, with data */ | ||
170 | # ifndef S_ISOFD | ||
171 | # define S_ISOFD(p) 0 | ||
172 | # endif | ||
173 | |||
174 | /* Cray DMF (data migration facility): off line, with no data */ | ||
175 | # ifndef S_ISOFL | ||
176 | # define S_ISOFL(p) 0 | ||
177 | # endif | ||
178 | |||
179 | /* 4.4BSD whiteout */ | ||
180 | # ifndef S_ISWHT | ||
181 | # define S_ISWHT(m) 0 | ||
182 | # endif | ||
183 | |||
184 | /* If any of the following are undefined, | ||
185 | define them to their de facto standard values. */ | ||
186 | # if !S_ISUID | ||
187 | # define S_ISUID 04000 | ||
188 | # endif | ||
189 | # if !S_ISGID | ||
190 | # define S_ISGID 02000 | ||
191 | # endif | ||
192 | |||
193 | /* S_ISVTX is a common extension to POSIX. */ | ||
194 | # ifndef S_ISVTX | ||
195 | # define S_ISVTX 01000 | ||
196 | # endif | ||
197 | |||
198 | # if !S_IRUSR && S_IREAD | ||
199 | # define S_IRUSR S_IREAD | ||
200 | # endif | ||
201 | # if !S_IRUSR | ||
202 | # define S_IRUSR 00400 | ||
203 | # endif | ||
204 | # if !S_IRGRP | ||
205 | # define S_IRGRP (S_IRUSR >> 3) | ||
206 | # endif | ||
207 | # if !S_IROTH | ||
208 | # define S_IROTH (S_IRUSR >> 6) | ||
209 | # endif | ||
210 | |||
211 | # if !S_IWUSR && S_IWRITE | ||
212 | # define S_IWUSR S_IWRITE | ||
213 | # endif | ||
214 | # if !S_IWUSR | ||
215 | # define S_IWUSR 00200 | ||
216 | # endif | ||
217 | # if !S_IWGRP | ||
218 | # define S_IWGRP (S_IWUSR >> 3) | ||
219 | # endif | ||
220 | # if !S_IWOTH | ||
221 | # define S_IWOTH (S_IWUSR >> 6) | ||
222 | # endif | ||
223 | |||
224 | # if !S_IXUSR && S_IEXEC | ||
225 | # define S_IXUSR S_IEXEC | ||
226 | # endif | ||
227 | # if !S_IXUSR | ||
228 | # define S_IXUSR 00100 | ||
229 | # endif | ||
230 | # if !S_IXGRP | ||
231 | # define S_IXGRP (S_IXUSR >> 3) | ||
232 | # endif | ||
233 | # if !S_IXOTH | ||
234 | # define S_IXOTH (S_IXUSR >> 6) | ||
235 | # endif | ||
236 | |||
237 | # if !S_IRWXU | ||
238 | # define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) | ||
239 | # endif | ||
240 | # if !S_IRWXG | ||
241 | # define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) | ||
242 | # endif | ||
243 | # if !S_IRWXO | ||
244 | # define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) | ||
245 | # endif | ||
246 | |||
247 | /* S_IXUGO is a common extension to POSIX. */ | ||
248 | # if !S_IXUGO | ||
249 | # define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH) | ||
250 | # endif | ||
251 | |||
252 | # ifndef S_IRWXUGO | ||
253 | # define S_IRWXUGO (S_IRWXU | S_IRWXG | S_IRWXO) | ||
254 | # endif | ||
255 | |||
256 | /* All the mode bits that can be affected by chmod. */ | ||
257 | # define CHMOD_MODE_BITS \ | ||
258 | (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO) | ||
259 | |||
260 | #endif /* STAT_MACROS_H */ |
mailbox/stdbool_.h
deleted
100644 → 0
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@ | ||
78 | typedef 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 | ||
100 | enum { false = 0, true = 1 }; | ||
101 | # else | ||
102 | /* With this compiler, trust the _Bool type if the compiler has it. */ | ||
103 | # if !@HAVE__BOOL@ | ||
104 | typedef 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 */ |
mailbox/stdint_.h
deleted
100644 → 0
1 | /* Copyright (C) 2001-2002, 2004-2006 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 | MacOS X 10.4.6 <sys/types.h> includes <stdint.h> (which is us), but | ||
52 | relies on the system <stdint.h> definitions, so include | ||
53 | <sys/types.h> after @ABSOLUTE_STDINT_H@. */ | ||
54 | #if @HAVE_SYS_TYPES_H@ | ||
55 | # include <sys/types.h> | ||
56 | #endif | ||
57 | |||
58 | /* Get LONG_MIN, LONG_MAX, ULONG_MAX. */ | ||
59 | #include <limits.h> | ||
60 | |||
61 | #if @HAVE_INTTYPES_H@ | ||
62 | /* In OpenBSD 3.8, <inttypes.h> includes <machine/types.h>, which defines | ||
63 | int{8,16,32,64}_t, uint{8,16,32,64}_t and __BIT_TYPES_DEFINED__. | ||
64 | <inttypes.h> also defines intptr_t and uintptr_t. */ | ||
65 | # define _GL_JUST_INCLUDE_ABSOLUTE_INTTYPES_H | ||
66 | # include <inttypes.h> | ||
67 | # undef _GL_JUST_INCLUDE_ABSOLUTE_INTTYPES_H | ||
68 | #elif @HAVE_SYS_INTTYPES_H@ | ||
69 | /* Solaris 7 <sys/inttypes.h> has the types except the *_fast*_t types, and | ||
70 | the macros except for *_FAST*_*, INTPTR_MIN, PTRDIFF_MIN, PTRDIFF_MAX. */ | ||
71 | # include <sys/inttypes.h> | ||
72 | #endif | ||
73 | |||
74 | #if @HAVE_SYS_BITYPES_H@ && ! defined __BIT_TYPES_DEFINED__ | ||
75 | /* Linux libc4 >= 4.6.7 and libc5 have a <sys/bitypes.h> that defines | ||
76 | int{8,16,32,64}_t and __BIT_TYPES_DEFINED__. In libc5 >= 5.2.2 it is | ||
77 | included by <sys/types.h>. */ | ||
78 | # include <sys/bitypes.h> | ||
79 | #endif | ||
80 | |||
81 | #if ! defined __cplusplus || defined __STDC_CONSTANT_MACROS | ||
82 | |||
83 | /* Get WCHAR_MIN, WCHAR_MAX. */ | ||
84 | # if @HAVE_WCHAR_H@ && ! (defined WCHAR_MIN && defined WCHAR_MAX) | ||
85 | /* BSD/OS 4.1 has a bug: <stdio.h> and <time.h> must be included before | ||
86 | <wchar.h>. */ | ||
87 | # include <stdio.h> | ||
88 | # include <time.h> | ||
89 | # include <wchar.h> | ||
90 | # endif | ||
91 | |||
92 | #endif | ||
93 | |||
94 | /* Minimum and maximum values for a integer type under the usual assumption. | ||
95 | Return an unspecified value if BITS == 0, adding a check to pacify | ||
96 | picky compilers. */ | ||
97 | |||
98 | #define _STDINT_MIN(signed, bits, zero) \ | ||
99 | ((signed) ? (- ((zero) + 1) << ((bits) ? (bits) - 1 : 0)) : (zero)) | ||
100 | |||
101 | #define _STDINT_MAX(signed, bits, zero) \ | ||
102 | ((signed) \ | ||
103 | ? ~ _STDINT_MIN (signed, bits, zero) \ | ||
104 | : ((((zero) + 1) << ((bits) ? (bits) - 1 : 0)) - 1) * 2 + 1) | ||
105 | |||
106 | /* 7.18.1.1. Exact-width integer types */ | ||
107 | |||
108 | /* Here we assume a standard architecture where the hardware integer | ||
109 | types have 8, 16, 32, optionally 64 bits. */ | ||
110 | |||
111 | #undef int8_t | ||
112 | #undef uint8_t | ||
113 | #define int8_t signed char | ||
114 | #define uint8_t unsigned char | ||
115 | |||
116 | #undef int16_t | ||
117 | #undef uint16_t | ||
118 | #define int16_t short int | ||
119 | #define uint16_t unsigned short int | ||
120 | |||
121 | #undef int32_t | ||
122 | #undef uint32_t | ||
123 | #define int32_t int | ||
124 | #define uint32_t unsigned int | ||
125 | |||
126 | #undef int64_t | ||
127 | #undef uint64_t | ||
128 | #if LONG_MAX >> 31 >> 31 == 1 | ||
129 | # define int64_t long int | ||
130 | # define uint64_t unsigned long int | ||
131 | #elif defined _MSC_VER | ||
132 | # define int64_t __int64 | ||
133 | # define uint64_t unsigned __int64 | ||
134 | #elif @HAVE_LONG_LONG_INT@ | ||
135 | # define int64_t long long int | ||
136 | # define uint64_t unsigned long long int | ||
137 | #endif | ||
138 | |||
139 | /* Avoid collision with Solaris 2.5.1 <pthread.h> etc. */ | ||
140 | #define _UINT8_T | ||
141 | #define _UINT32_T | ||
142 | #define _UINT64_T | ||
143 | |||
144 | |||
145 | /* 7.18.1.2. Minimum-width integer types */ | ||
146 | |||
147 | /* Here we assume a standard architecture where the hardware integer | ||
148 | types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types | ||
149 | are the same as the corresponding N_t types. */ | ||
150 | |||
151 | #undef int_least8_t | ||
152 | #undef uint_least8_t | ||
153 | #undef int_least16_t | ||
154 | #undef uint_least16_t | ||
155 | #undef int_least32_t | ||
156 | #undef uint_least32_t | ||
157 | #undef int_least64_t | ||
158 | #undef uint_least64_t | ||
159 | #define int_least8_t int8_t | ||
160 | #define uint_least8_t uint8_t | ||
161 | #define int_least16_t int16_t | ||
162 | #define uint_least16_t uint16_t | ||
163 | #define int_least32_t int32_t | ||
164 | #define uint_least32_t uint32_t | ||
165 | #ifdef int64_t | ||
166 | # define int_least64_t int64_t | ||
167 | # define uint_least64_t uint64_t | ||
168 | #endif | ||
169 | |||
170 | /* 7.18.1.3. Fastest minimum-width integer types */ | ||
171 | |||
172 | /* Note: Other <stdint.h> substitutes may define these types differently. | ||
173 | It is not recommended to use these types in public header files. */ | ||
174 | |||
175 | /* Here we assume a standard architecture where the hardware integer | ||
176 | types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types | ||
177 | are taken from the same list of types. Assume that 'long int' | ||
178 | is fast enough for all narrower integers. */ | ||
179 | |||
180 | #undef int_fast8_t | ||
181 | #undef uint_fast8_t | ||
182 | #undef int_fast16_t | ||
183 | #undef uint_fast16_t | ||
184 | #undef int_fast32_t | ||
185 | #undef uint_fast32_t | ||
186 | #undef int_fast64_t | ||
187 | #undef uint_fast64_t | ||
188 | #define int_fast8_t long int | ||
189 | #define uint_fast8_t unsigned int_fast8_t | ||
190 | #define int_fast16_t long int | ||
191 | #define uint_fast16_t unsigned int_fast16_t | ||
192 | #define int_fast32_t long int | ||
193 | #define uint_fast32_t unsigned int_fast32_t | ||
194 | #ifdef int64_t | ||
195 | # define int_fast64_t int64_t | ||
196 | # define uint_fast64_t uint64_t | ||
197 | #endif | ||
198 | |||
199 | /* 7.18.1.4. Integer types capable of holding object pointers */ | ||
200 | |||
201 | #undef intptr_t | ||
202 | #undef uintptr_t | ||
203 | #define intptr_t long int | ||
204 | #define uintptr_t unsigned long int | ||
205 | |||
206 | /* 7.18.1.5. Greatest-width integer types */ | ||
207 | |||
208 | /* Note: These types are compiler dependent. It may be unwise to use them in | ||
209 | public header files. */ | ||
210 | |||
211 | #undef intmax_t | ||
212 | #undef uintmax_t | ||
213 | #if @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1 | ||
214 | # define intmax_t long long int | ||
215 | # define uintmax_t unsigned long long int | ||
216 | #elif defined int64_t | ||
217 | # define intmax_t int64_t | ||
218 | # define uintmax_t uint64_t | ||
219 | #else | ||
220 | # define intmax_t long int | ||
221 | # define uintmax_t unsigned long int | ||
222 | #endif | ||
223 | |||
224 | /* 7.18.2. Limits of specified-width integer types */ | ||
225 | |||
226 | #if ! defined __cplusplus || defined __STDC_LIMIT_MACROS | ||
227 | |||
228 | /* 7.18.2.1. Limits of exact-width integer types */ | ||
229 | |||
230 | /* Here we assume a standard architecture where the hardware integer | ||
231 | types have 8, 16, 32, optionally 64 bits. */ | ||
232 | |||
233 | #undef INT8_MIN | ||
234 | #undef INT8_MAX | ||
235 | #undef UINT8_MAX | ||
236 | #define INT8_MIN (~ INT8_MAX) | ||
237 | #define INT8_MAX 127 | ||
238 | #define UINT8_MAX 255 | ||
239 | |||
240 | #undef INT16_MIN | ||
241 | #undef INT16_MAX | ||
242 | #undef UINT16_MAX | ||
243 | #define INT16_MIN (~ INT16_MAX) | ||
244 | #define INT16_MAX 32767 | ||
245 | #define UINT16_MAX 65535 | ||
246 | |||
247 | #undef INT32_MIN | ||
248 | #undef INT32_MAX | ||
249 | #undef UINT32_MAX | ||
250 | #define INT32_MIN (~ INT32_MAX) | ||
251 | #define INT32_MAX 2147483647 | ||
252 | #define UINT32_MAX 4294967295U | ||
253 | |||
254 | #undef INT64_MIN | ||
255 | #undef INT64_MAX | ||
256 | #undef UINT64_MAX | ||
257 | #ifdef int64_t | ||
258 | # define INT64_MIN (~ INT64_MAX) | ||
259 | # define INT64_MAX INTMAX_C (9223372036854775807) | ||
260 | # define UINT64_MAX UINTMAX_C (18446744073709551615) | ||
261 | #endif | ||
262 | |||
263 | /* 7.18.2.2. Limits of minimum-width integer types */ | ||
264 | |||
265 | /* Here we assume a standard architecture where the hardware integer | ||
266 | types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types | ||
267 | are the same as the corresponding N_t types. */ | ||
268 | |||
269 | #undef INT_LEAST8_MIN | ||
270 | #undef INT_LEAST8_MAX | ||
271 | #undef UINT_LEAST8_MAX | ||
272 | #define INT_LEAST8_MIN INT8_MIN | ||
273 | #define INT_LEAST8_MAX INT8_MAX | ||
274 | #define UINT_LEAST8_MAX UINT8_MAX | ||
275 | |||
276 | #undef INT_LEAST16_MIN | ||
277 | #undef INT_LEAST16_MAX | ||
278 | #undef UINT_LEAST16_MAX | ||
279 | #define INT_LEAST16_MIN INT16_MIN | ||
280 | #define INT_LEAST16_MAX INT16_MAX | ||
281 | #define UINT_LEAST16_MAX UINT16_MAX | ||
282 | |||
283 | #undef INT_LEAST32_MIN | ||
284 | #undef INT_LEAST32_MAX | ||
285 | #undef UINT_LEAST32_MAX | ||
286 | #define INT_LEAST32_MIN INT32_MIN | ||
287 | #define INT_LEAST32_MAX INT32_MAX | ||
288 | #define UINT_LEAST32_MAX UINT32_MAX | ||
289 | |||
290 | #undef INT_LEAST64_MIN | ||
291 | #undef INT_LEAST64_MAX | ||
292 | #undef UINT_LEAST64_MAX | ||
293 | #ifdef int64_t | ||
294 | # define INT_LEAST64_MIN INT64_MIN | ||
295 | # define INT_LEAST64_MAX INT64_MAX | ||
296 | # define UINT_LEAST64_MAX UINT64_MAX | ||
297 | #endif | ||
298 | |||
299 | /* 7.18.2.3. Limits of fastest minimum-width integer types */ | ||
300 | |||
301 | /* Here we assume a standard architecture where the hardware integer | ||
302 | types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types | ||
303 | are taken from the same list of types. */ | ||
304 | |||
305 | #undef INT_FAST8_MIN | ||
306 | #undef INT_FAST8_MAX | ||
307 | #undef UINT_FAST8_MAX | ||
308 | #define INT_FAST8_MIN LONG_MIN | ||
309 | #define INT_FAST8_MAX LONG_MAX | ||
310 | #define UINT_FAST8_MAX ULONG_MAX | ||
311 | |||
312 | #undef INT_FAST16_MIN | ||
313 | #undef INT_FAST16_MAX | ||
314 | #undef UINT_FAST16_MAX | ||
315 | #define INT_FAST16_MIN LONG_MIN | ||
316 | #define INT_FAST16_MAX LONG_MAX | ||
317 | #define UINT_FAST16_MAX ULONG_MAX | ||
318 | |||
319 | #undef INT_FAST32_MIN | ||
320 | #undef INT_FAST32_MAX | ||
321 | #undef UINT_FAST32_MAX | ||
322 | #define INT_FAST32_MIN LONG_MIN | ||
323 | #define INT_FAST32_MAX LONG_MAX | ||
324 | #define UINT_FAST32_MAX ULONG_MAX | ||
325 | |||
326 | #undef INT_FAST64_MIN | ||
327 | #undef INT_FAST64_MAX | ||
328 | #undef UINT_FAST64_MAX | ||
329 | #ifdef int64_t | ||
330 | # define INT_FAST64_MIN INT64_MIN | ||
331 | # define INT_FAST64_MAX INT64_MAX | ||
332 | # define UINT_FAST64_MAX UINT64_MAX | ||
333 | #endif | ||
334 | |||
335 | /* 7.18.2.4. Limits of integer types capable of holding object pointers */ | ||
336 | |||
337 | #undef INTPTR_MIN | ||
338 | #undef INTPTR_MAX | ||
339 | #undef UINTPTR_MAX | ||
340 | #define INTPTR_MIN LONG_MIN | ||
341 | #define INTPTR_MAX LONG_MAX | ||
342 | #define UINTPTR_MAX ULONG_MAX | ||
343 | |||
344 | /* 7.18.2.5. Limits of greatest-width integer types */ | ||
345 | |||
346 | #undef INTMAX_MIN | ||
347 | #undef INTMAX_MAX | ||
348 | #undef UINTMAX_MAX | ||
349 | #define INTMAX_MIN (~ INTMAX_MAX) | ||
350 | #ifdef INT64_MAX | ||
351 | # define INTMAX_MAX INT64_MAX | ||
352 | # define UINTMAX_MAX UINT64_MAX | ||
353 | #else | ||
354 | # define INTMAX_MAX INT32_MAX | ||
355 | # define UINTMAX_MAX UINT32_MAX | ||
356 | #endif | ||
357 | |||
358 | /* 7.18.3. Limits of other integer types */ | ||
359 | |||
360 | /* ptrdiff_t limits */ | ||
361 | #undef PTRDIFF_MIN | ||
362 | #undef PTRDIFF_MAX | ||
363 | #define PTRDIFF_MIN \ | ||
364 | _STDINT_MIN (1, @BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@) | ||
365 | #define PTRDIFF_MAX \ | ||
366 | _STDINT_MAX (1, @BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@) | ||
367 | |||
368 | /* sig_atomic_t limits */ | ||
369 | #undef SIG_ATOMIC_MIN | ||
370 | #undef SIG_ATOMIC_MAX | ||
371 | #define SIG_ATOMIC_MIN \ | ||
372 | _STDINT_MIN (@HAVE_SIGNED_SIG_ATOMIC_T@, @BITSIZEOF_SIG_ATOMIC_T@, \ | ||
373 | 0@SIG_ATOMIC_T_SUFFIX@) | ||
374 | #define SIG_ATOMIC_MAX \ | ||
375 | _STDINT_MAX (@HAVE_SIGNED_SIG_ATOMIC_T@, @BITSIZEOF_SIG_ATOMIC_T@, \ | ||
376 | 0@SIG_ATOMIC_T_SUFFIX@) | ||
377 | |||
378 | |||
379 | /* size_t limit */ | ||
380 | #undef SIZE_MAX | ||
381 | #define SIZE_MAX _STDINT_MAX (0, @BITSIZEOF_SIZE_T@, 0@SIZE_T_SUFFIX@) | ||
382 | |||
383 | /* wchar_t limits */ | ||
384 | #undef WCHAR_MIN | ||
385 | #undef WCHAR_MAX | ||
386 | #define WCHAR_MIN \ | ||
387 | _STDINT_MIN (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@) | ||
388 | #define WCHAR_MAX \ | ||
389 | _STDINT_MAX (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@) | ||
390 | |||
391 | /* wint_t limits */ | ||
392 | #undef WINT_MIN | ||
393 | #undef WINT_MAX | ||
394 | #define WINT_MIN \ | ||
395 | _STDINT_MIN (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@) | ||
396 | #define WINT_MAX \ | ||
397 | _STDINT_MAX (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@) | ||
398 | |||
399 | #endif /* !defined __cplusplus || defined __STDC_LIMIT_MACROS */ | ||
400 | |||
401 | /* 7.18.4. Macros for integer constants */ | ||
402 | |||
403 | #if ! defined __cplusplus || defined __STDC_CONSTANT_MACROS | ||
404 | |||
405 | /* 7.18.4.1. Macros for minimum-width integer constants */ | ||
406 | /* According to ISO C 99 Technical Corrigendum 1 */ | ||
407 | |||
408 | /* Here we assume a standard architecture where the hardware integer | ||
409 | types have 8, 16, 32, optionally 64 bits, and int is 32 bits. */ | ||
410 | |||
411 | #undef INT8_C | ||
412 | #undef UINT8_C | ||
413 | #define INT8_C(x) x | ||
414 | #define UINT8_C(x) x | ||
415 | |||
416 | #undef INT16_C | ||
417 | #undef UINT16_C | ||
418 | #define INT16_C(x) x | ||
419 | #define UINT16_C(x) x | ||
420 | |||
421 | #undef INT32_C | ||
422 | #undef UINT32_C | ||
423 | #define INT32_C(x) x | ||
424 | #define UINT32_C(x) x ## U | ||
425 | |||
426 | #undef INT64_C | ||
427 | #undef UINT64_C | ||
428 | #if LONG_MAX >> 31 >> 31 == 1 | ||
429 | # define INT64_C(x) x##L | ||
430 | # define UINT64_C(x) x##UL | ||
431 | #elif defined _MSC_VER | ||
432 | # define INT64_C(x) x##i64 | ||
433 | # define UINT64_C(x) x##ui64 | ||
434 | #elif @HAVE_LONG_LONG_INT@ | ||
435 | # define INT64_C(x) x##LL | ||
436 | # define UINT64_C(x) x##ULL | ||
437 | #endif | ||
438 | |||
439 | /* 7.18.4.2. Macros for greatest-width integer constants */ | ||
440 | |||
441 | #undef INTMAX_C | ||
442 | #undef UINTMAX_C | ||
443 | #if @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1 | ||
444 | # define INTMAX_C(x) x##LL | ||
445 | # define UINTMAX_C(x) x##ULL | ||
446 | #elif defined int64_t | ||
447 | # define INTMAX_C(x) INT64_C(x) | ||
448 | # define UINTMAX_C(x) UINT64_C(x) | ||
449 | #else | ||
450 | # define INTMAX_C(x) x##L | ||
451 | # define UINTMAX_C(x) x##UL | ||
452 | #endif | ||
453 | |||
454 | #endif /* !defined __cplusplus || defined __STDC_CONSTANT_MACROS */ | ||
455 | |||
456 | #endif /* _GL_STDINT_H */ |
mailbox/strcase.h
deleted
100644 → 0
1 | /* Case-insensitive string comparison functions. | ||
2 | Copyright (C) 1995-1996, 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 _STRCASE_H | ||
19 | #define _STRCASE_H | ||
20 | |||
21 | #include <stddef.h> | ||
22 | |||
23 | |||
24 | #ifdef __cplusplus | ||
25 | extern "C" { | ||
26 | #endif | ||
27 | |||
28 | |||
29 | /* Compare strings S1 and S2, ignoring case, returning less than, equal to or | ||
30 | greater than zero if S1 is lexicographically less than, equal to or greater | ||
31 | than S2. | ||
32 | Note: This function may, in multibyte locales, return 0 for strings of | ||
33 | different lengths! */ | ||
34 | extern int strcasecmp (const char *s1, const char *s2); | ||
35 | |||
36 | /* Compare no more than N characters of strings S1 and S2, ignoring case, | ||
37 | returning less than, equal to or greater than zero if S1 is | ||
38 | lexicographically less than, equal to or greater than S2. | ||
39 | Note: This function can not work correctly in multibyte locales. */ | ||
40 | extern int strncasecmp (const char *s1, const char *s2, size_t n); | ||
41 | |||
42 | |||
43 | #ifdef __cplusplus | ||
44 | } | ||
45 | #endif | ||
46 | |||
47 | |||
48 | #endif /* _STRCASE_H */ |
mailbox/strcasecmp.c
deleted
100644 → 0
1 | /* Case-insensitive string comparison function. | ||
2 | Copyright (C) 1998, 1999, 2005 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 | #ifdef HAVE_CONFIG_H | ||
21 | # include <config.h> | ||
22 | #endif | ||
23 | |||
24 | /* Specification. */ | ||
25 | #include "strcase.h" | ||
26 | |||
27 | #include <ctype.h> | ||
28 | #include <limits.h> | ||
29 | |||
30 | #if HAVE_MBRTOWC | ||
31 | # include "mbuiter.h" | ||
32 | #endif | ||
33 | |||
34 | #define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch)) | ||
35 | |||
36 | /* Compare strings S1 and S2, ignoring case, returning less than, equal to or | ||
37 | greater than zero if S1 is lexicographically less than, equal to or greater | ||
38 | than S2. | ||
39 | Note: This function may, in multibyte locales, return 0 for strings of | ||
40 | different lengths! */ | ||
41 | int | ||
42 | strcasecmp (const char *s1, const char *s2) | ||
43 | { | ||
44 | if (s1 == s2) | ||
45 | return 0; | ||
46 | |||
47 | /* Be careful not to look at the entire extent of s1 or s2 until needed. | ||
48 | This is useful because when two strings differ, the difference is | ||
49 | most often already in the very few first characters. */ | ||
50 | #if HAVE_MBRTOWC | ||
51 | if (MB_CUR_MAX > 1) | ||
52 | { | ||
53 | mbui_iterator_t iter1; | ||
54 | mbui_iterator_t iter2; | ||
55 | |||
56 | mbui_init (iter1, s1); | ||
57 | mbui_init (iter2, s2); | ||
58 | |||
59 | while (mbui_avail (iter1) && mbui_avail (iter2)) | ||
60 | { | ||
61 | int cmp = mb_casecmp (mbui_cur (iter1), mbui_cur (iter2)); | ||
62 | |||
63 | if (cmp != 0) | ||
64 | return cmp; | ||
65 | |||
66 | mbui_advance (iter1); | ||
67 | mbui_advance (iter2); | ||
68 | } | ||
69 | if (mbui_avail (iter1)) | ||
70 | /* s2 terminated before s1. */ | ||
71 | return 1; | ||
72 | if (mbui_avail (iter2)) | ||
73 | /* s1 terminated before s2. */ | ||
74 | return -1; | ||
75 | return 0; | ||
76 | } | ||
77 | else | ||
78 | #endif | ||
79 | { | ||
80 | const unsigned char *p1 = (const unsigned char *) s1; | ||
81 | const unsigned char *p2 = (const unsigned char *) s2; | ||
82 | unsigned char c1, c2; | ||
83 | |||
84 | do | ||
85 | { | ||
86 | c1 = TOLOWER (*p1); | ||
87 | c2 = TOLOWER (*p2); | ||
88 | |||
89 | if (c1 == '\0') | ||
90 | break; | ||
91 | |||
92 | ++p1; | ||
93 | ++p2; | ||
94 | } | ||
95 | while (c1 == c2); | ||
96 | |||
97 | if (UCHAR_MAX <= INT_MAX) | ||
98 | return c1 - c2; | ||
99 | else | ||
100 | /* On machines where 'char' and 'int' are types of the same size, the | ||
101 | difference of two 'unsigned char' values - including the sign bit - | ||
102 | doesn't fit in an 'int'. */ | ||
103 | return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0); | ||
104 | } | ||
105 | } |
mailbox/strchrnul.c
deleted
100644 → 0
1 | /* Searching in a string. | ||
2 | Copyright (C) 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 | /* Specification. */ | ||
19 | #include "strchrnul.h" | ||
20 | |||
21 | /* Find the first occurrence of C in S or the final NUL byte. */ | ||
22 | char * | ||
23 | strchrnul (const char *s, int c_in) | ||
24 | { | ||
25 | char c = c_in; | ||
26 | while (*s && (*s != c)) | ||
27 | s++; | ||
28 | |||
29 | return (char *) s; | ||
30 | } |
mailbox/strchrnul.h
deleted
100644 → 0
1 | /* Searching in a string. | ||
2 | Copyright (C) 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 | #if HAVE_STRCHRNUL | ||
19 | |||
20 | /* Get strchrnul() declaration. */ | ||
21 | #include <string.h> | ||
22 | |||
23 | #else | ||
24 | |||
25 | /* Find the first occurrence of C in S or the final NUL byte. */ | ||
26 | extern char *strchrnul (const char *s, int c_in); | ||
27 | |||
28 | #endif |
mailbox/strdup.c
deleted
100644 → 0
1 | /* Copyright (C) 1991, 1996, 1997, 1998, 2002, 2003, 2004 Free Software | ||
2 | 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 | #ifdef HAVE_CONFIG_H | ||
21 | # include <config.h> | ||
22 | #endif | ||
23 | |||
24 | #ifndef _LIBC | ||
25 | /* Get specification. */ | ||
26 | # include "strdup.h" | ||
27 | #endif | ||
28 | |||
29 | #include <stdlib.h> | ||
30 | #include <string.h> | ||
31 | |||
32 | #undef __strdup | ||
33 | #undef strdup | ||
34 | |||
35 | #ifndef weak_alias | ||
36 | # define __strdup strdup | ||
37 | #endif | ||
38 | |||
39 | /* Duplicate S, returning an identical malloc'd string. */ | ||
40 | char * | ||
41 | __strdup (const char *s) | ||
42 | { | ||
43 | size_t len = strlen (s) + 1; | ||
44 | void *new = malloc (len); | ||
45 | |||
46 | if (new == NULL) | ||
47 | return NULL; | ||
48 | |||
49 | return (char *) memcpy (new, s, len); | ||
50 | } | ||
51 | #ifdef libc_hidden_def | ||
52 | libc_hidden_def (__strdup) | ||
53 | #endif | ||
54 | #ifdef weak_alias | ||
55 | weak_alias (__strdup, strdup) | ||
56 | #endif |
mailbox/strdup.h
deleted
100644 → 0
1 | /* strdup.h -- duplicate a string | ||
2 | Copyright (C) 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., 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 | #if defined HAVE_DECL_STRDUP && !HAVE_DECL_STRDUP && !defined strdup | ||
25 | /* Duplicate S, returning an identical malloc'd string. */ | ||
26 | extern char *strdup (const char *s); | ||
27 | #endif | ||
28 | |||
29 | #endif /* STRDUP_H_ */ |
mailbox/strncasecmp.c
deleted
100644 → 0
1 | /* strncasecmp.c -- case insensitive string comparator | ||
2 | Copyright (C) 1998, 1999, 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 | #ifdef HAVE_CONFIG_H | ||
19 | # include <config.h> | ||
20 | #endif | ||
21 | |||
22 | /* Specification. */ | ||
23 | #include "strcase.h" | ||
24 | |||
25 | #include <ctype.h> | ||
26 | #include <limits.h> | ||
27 | |||
28 | #define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch)) | ||
29 | |||
30 | /* Compare no more than N bytes of strings S1 and S2, | ||
31 | ignoring case, returning less than, equal to or | ||
32 | greater than zero if S1 is lexicographically less | ||
33 | than, equal to or greater than S2. */ | ||
34 | |||
35 | int | ||
36 | strncasecmp (const char *s1, const char *s2, size_t n) | ||
37 | { | ||
38 | register const unsigned char *p1 = (const unsigned char *) s1; | ||
39 | register const unsigned char *p2 = (const unsigned char *) s2; | ||
40 | unsigned char c1, c2; | ||
41 | |||
42 | if (p1 == p2 || n == 0) | ||
43 | return 0; | ||
44 | |||
45 | do | ||
46 | { | ||
47 | c1 = TOLOWER (*p1); | ||
48 | c2 = TOLOWER (*p2); | ||
49 | |||
50 | if (--n == 0 || c1 == '\0') | ||
51 | break; | ||
52 | |||
53 | ++p1; | ||
54 | ++p2; | ||
55 | } | ||
56 | while (c1 == c2); | ||
57 | |||
58 | if (UCHAR_MAX <= INT_MAX) | ||
59 | return c1 - c2; | ||
60 | else | ||
61 | /* On machines where 'char' and 'int' are types of the same size, the | ||
62 | difference of two 'unsigned char' values - including the sign bit - | ||
63 | doesn't fit in an 'int'. */ | ||
64 | return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0); | ||
65 | } |
mailbox/strndup.c
deleted
100644 → 0
1 | /* Copyright (C) 1996, 1997, 1998, 2001, 2002, 2003, 2005, 2006 Free | ||
2 | Software Foundation, Inc. | ||
3 | |||
4 | NOTE: The canonical source of this file is maintained with the GNU C Library. | ||
5 | Bugs can be reported to bug-glibc@prep.ai.mit.edu. | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify it | ||
8 | under the terms of the GNU General Public License as published by the | ||
9 | Free Software Foundation; either version 2, or (at your option) any | ||
10 | 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 | #ifdef HAVE_CONFIG_H | ||
22 | # include <config.h> | ||
23 | #endif | ||
24 | #if !_LIBC | ||
25 | # include "strndup.h" | ||
26 | #endif | ||
27 | |||
28 | #include <stdlib.h> | ||
29 | #include <string.h> | ||
30 | |||
31 | #if !_LIBC | ||
32 | # include "strnlen.h" | ||
33 | # ifndef __strnlen | ||
34 | # define __strnlen strnlen | ||
35 | # endif | ||
36 | #endif | ||
37 | |||
38 | #undef __strndup | ||
39 | #if _LIBC | ||
40 | # undef strndup | ||
41 | #endif | ||
42 | |||
43 | #ifndef weak_alias | ||
44 | # define __strndup strndup | ||
45 | #endif | ||
46 | |||
47 | char * | ||
48 | __strndup (s, n) | ||
49 | const char *s; | ||
50 | size_t n; | ||
51 | { | ||
52 | size_t len = __strnlen (s, n); | ||
53 | char *new = malloc (len + 1); | ||
54 | |||
55 | if (new == NULL) | ||
56 | return NULL; | ||
57 | |||
58 | new[len] = '\0'; | ||
59 | return memcpy (new, s, len); | ||
60 | } | ||
61 | #ifdef libc_hidden_def | ||
62 | libc_hidden_def (__strndup) | ||
63 | #endif | ||
64 | #ifdef weak_alias | ||
65 | weak_alias (__strndup, strndup) | ||
66 | #endif |
mailbox/strndup.h
deleted
100644 → 0
1 | /* Duplicate a size-bounded string. | ||
2 | Copyright (C) 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 | #if HAVE_STRNDUP | ||
19 | |||
20 | /* Get strndup() declaration. */ | ||
21 | #include <string.h> | ||
22 | |||
23 | #else | ||
24 | |||
25 | #include <stddef.h> | ||
26 | |||
27 | /* Return a newly allocated copy of at most N bytes of STRING. */ | ||
28 | extern char *strndup (const char *string, size_t n); | ||
29 | |||
30 | #endif |
mailbox/strnlen.c
deleted
100644 → 0
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 | #ifdef HAVE_CONFIG_H | ||
20 | # include <config.h> | ||
21 | #endif | ||
22 | |||
23 | #include "strnlen.h" | ||
24 | |||
25 | /* Find the length of STRING, but scan at most MAXLEN characters. | ||
26 | If no '\0' terminator is found in that many characters, return MAXLEN. */ | ||
27 | |||
28 | size_t | ||
29 | strnlen (const char *string, size_t maxlen) | ||
30 | { | ||
31 | const char *end = memchr (string, '\0', maxlen); | ||
32 | return end ? (size_t) (end - string) : maxlen; | ||
33 | } |
mailbox/strnlen.h
deleted
100644 → 0
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. */ | ||
29 | extern size_t strnlen(const char *string, size_t maxlen); | ||
30 | #endif | ||
31 | |||
32 | #endif /* STRNLEN_H */ |
mailbox/strnlen1.c
deleted
100644 → 0
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 | #ifdef HAVE_CONFIG_H | ||
19 | # include <config.h> | ||
20 | #endif | ||
21 | |||
22 | /* Specification. */ | ||
23 | #include "strnlen1.h" | ||
24 | |||
25 | #include <string.h> | ||
26 | |||
27 | /* Find the length of STRING + 1, but scan at most MAXLEN bytes. | ||
28 | If no '\0' terminator is found in that many characters, return MAXLEN. */ | ||
29 | /* This is the same as strnlen (string, maxlen - 1) + 1. */ | ||
30 | size_t | ||
31 | strnlen1 (const char *string, size_t maxlen) | ||
32 | { | ||
33 | const char *end = memchr (string, '\0', maxlen); | ||
34 | if (end != NULL) | ||
35 | return end - string + 1; | ||
36 | else | ||
37 | return maxlen; | ||
38 | } |
mailbox/strnlen1.h
deleted
100644 → 0
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 | ||
25 | extern "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. */ | ||
32 | extern size_t strnlen1 (const char *string, size_t maxlen); | ||
33 | |||
34 | |||
35 | #ifdef __cplusplus | ||
36 | } | ||
37 | #endif | ||
38 | |||
39 | |||
40 | #endif /* _STRNLEN1_H */ |
mailbox/strtok_r.c
deleted
100644 → 0
1 | /* Reentrant string tokenizer. Generic version. | ||
2 | Copyright (C) 1991,1996-1999,2001,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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ | ||
18 | |||
19 | #ifdef HAVE_CONFIG_H | ||
20 | # include <config.h> | ||
21 | #endif | ||
22 | |||
23 | #include <string.h> | ||
24 | |||
25 | #undef strtok_r | ||
26 | #undef __strtok_r | ||
27 | |||
28 | #ifndef _LIBC | ||
29 | /* Get specification. */ | ||
30 | # include "strtok_r.h" | ||
31 | # define __strtok_r strtok_r | ||
32 | # define __rawmemchr strchr | ||
33 | #endif | ||
34 | |||
35 | /* Parse S into tokens separated by characters in DELIM. | ||
36 | If S is NULL, the saved pointer in SAVE_PTR is used as | ||
37 | the next starting point. For example: | ||
38 | char s[] = "-abc-=-def"; | ||
39 | char *sp; | ||
40 | x = strtok_r(s, "-", &sp); // x = "abc", sp = "=-def" | ||
41 | x = strtok_r(NULL, "-=", &sp); // x = "def", sp = NULL | ||
42 | x = strtok_r(NULL, "=", &sp); // x = NULL | ||
43 | // s = "abc\0-def\0" | ||
44 | */ | ||
45 | char * | ||
46 | __strtok_r (char *s, const char *delim, char **save_ptr) | ||
47 | { | ||
48 | char *token; | ||
49 | |||
50 | if (s == NULL) | ||
51 | s = *save_ptr; | ||
52 | |||
53 | /* Scan leading delimiters. */ | ||
54 | s += strspn (s, delim); | ||
55 | if (*s == '\0') | ||
56 | { | ||
57 | *save_ptr = s; | ||
58 | return NULL; | ||
59 | } | ||
60 | |||
61 | /* Find the end of the token. */ | ||
62 | token = s; | ||
63 | s = strpbrk (token, delim); | ||
64 | if (s == NULL) | ||
65 | /* This token finishes the string. */ | ||
66 | *save_ptr = __rawmemchr (token, '\0'); | ||
67 | else | ||
68 | { | ||
69 | /* Terminate the token and make *SAVE_PTR point past it. */ | ||
70 | *s = '\0'; | ||
71 | *save_ptr = s + 1; | ||
72 | } | ||
73 | return token; | ||
74 | } | ||
75 | #ifdef weak_alias | ||
76 | libc_hidden_def (__strtok_r) | ||
77 | weak_alias (__strtok_r, strtok_r) | ||
78 | #endif |
mailbox/strtok_r.h
deleted
100644 → 0
1 | /* Split string into tokens | ||
2 | Copyright (C) 2004-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 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 STRTOK_R_H | ||
20 | #define STRTOK_R_H | ||
21 | |||
22 | /* Get strtok_r declaration, if available. */ | ||
23 | #include <string.h> | ||
24 | |||
25 | /* Parse S into tokens separated by characters in DELIM. | ||
26 | If S is NULL, the saved pointer in SAVE_PTR is used as | ||
27 | the next starting point. For example: | ||
28 | char s[] = "-abc-=-def"; | ||
29 | char *sp; | ||
30 | x = strtok_r(s, "-", &sp); // x = "abc", sp = "=-def" | ||
31 | x = strtok_r(NULL, "-=", &sp); // x = "def", sp = NULL | ||
32 | x = strtok_r(NULL, "=", &sp); // x = NULL | ||
33 | // s = "abc\0-def\0" | ||
34 | |||
35 | This is a variant of strtok() that is multithread-safe. | ||
36 | |||
37 | For the POSIX documentation for this function, see: | ||
38 | http://www.opengroup.org/susv3xsh/strtok.html | ||
39 | |||
40 | Caveat: It modifies the original string. | ||
41 | Caveat: These functions cannot be used on constant strings. | ||
42 | Caveat: The identity of the delimiting character is lost. | ||
43 | Caveat: It doesn't work with multibyte strings unless all of the delimiter | ||
44 | characters are ASCII characters < 0x30. | ||
45 | |||
46 | See also strsep(). | ||
47 | */ | ||
48 | #if defined HAVE_DECL_STRTOK_R && !HAVE_DECL_STRTOK_R | ||
49 | extern char *strtok_r(char *restrict s, const char *restrict sep, | ||
50 | char **restrict lasts); | ||
51 | #endif | ||
52 | |||
53 | #endif /* STRTOK_R_H */ |
mailbox/sysexit_.h
deleted
100644 → 0
1 | /* exit() exit codes for some BSD system programs. | ||
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 | /* Written by Simon Josefsson based on sysexits(3) man page */ | ||
19 | |||
20 | #ifndef _SYSEXITS_H | ||
21 | #define _SYSEXITS_H | ||
22 | |||
23 | #define EX_OK 0 /* same value as EXIT_SUCCESS */ | ||
24 | |||
25 | #define EX_USAGE 64 | ||
26 | #define EX_DATAERR 65 | ||
27 | #define EX_NOINPUT 66 | ||
28 | #define EX_NOUSER 67 | ||
29 | #define EX_NOHOST 68 | ||
30 | #define EX_UNAVAILABLE 69 | ||
31 | #define EX_SOFTWARE 70 | ||
32 | #define EX_OSERR 71 | ||
33 | #define EX_OSFILE 72 | ||
34 | #define EX_CANTCREAT 73 | ||
35 | #define EX_IOERR 74 | ||
36 | #define EX_TEMPFAIL 75 | ||
37 | #define EX_PROTOCOL 76 | ||
38 | #define EX_NOPERM 77 | ||
39 | #define EX_CONFIG 78 | ||
40 | |||
41 | #endif /* _SYSEXITS_H */ |
mailbox/unlocked-io.h
deleted
100644 → 0
1 | /* Prefer faster, non-thread-safe stdio functions if available. | ||
2 | |||
3 | Copyright (C) 2001, 2002, 2003, 2004 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 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 Jim Meyering. */ | ||
20 | |||
21 | #ifndef UNLOCKED_IO_H | ||
22 | # define UNLOCKED_IO_H 1 | ||
23 | |||
24 | /* These are wrappers for functions/macros from the GNU C library, and | ||
25 | from other C libraries supporting POSIX's optional thread-safe functions. | ||
26 | |||
27 | The standard I/O functions are thread-safe. These *_unlocked ones are | ||
28 | more efficient but not thread-safe. That they're not thread-safe is | ||
29 | fine since all of the applications in this package are single threaded. | ||
30 | |||
31 | Also, some code that is shared with the GNU C library may invoke | ||
32 | the *_unlocked functions directly. On hosts that lack those | ||
33 | functions, invoke the non-thread-safe versions instead. */ | ||
34 | |||
35 | # include <stdio.h> | ||
36 | |||
37 | # if HAVE_DECL_CLEARERR_UNLOCKED | ||
38 | # undef clearerr | ||
39 | # define clearerr(x) clearerr_unlocked (x) | ||
40 | # else | ||
41 | # define clearerr_unlocked(x) clearerr (x) | ||
42 | # endif | ||
43 | |||
44 | # if HAVE_DECL_FEOF_UNLOCKED | ||
45 | # undef feof | ||
46 | # define feof(x) feof_unlocked (x) | ||
47 | # else | ||
48 | # define feof_unlocked(x) feof (x) | ||
49 | # endif | ||
50 | |||
51 | # if HAVE_DECL_FERROR_UNLOCKED | ||
52 | # undef ferror | ||
53 | # define ferror(x) ferror_unlocked (x) | ||
54 | # else | ||
55 | # define ferror_unlocked(x) ferror (x) | ||
56 | # endif | ||
57 | |||
58 | # if HAVE_DECL_FFLUSH_UNLOCKED | ||
59 | # undef fflush | ||
60 | # define fflush(x) fflush_unlocked (x) | ||
61 | # else | ||
62 | # define fflush_unlocked(x) fflush (x) | ||
63 | # endif | ||
64 | |||
65 | # if HAVE_DECL_FGETS_UNLOCKED | ||
66 | # undef fgets | ||
67 | # define fgets(x,y,z) fgets_unlocked (x,y,z) | ||
68 | # else | ||
69 | # define fgets_unlocked(x,y,z) fgets (x,y,z) | ||
70 | # endif | ||
71 | |||
72 | # if HAVE_DECL_FPUTC_UNLOCKED | ||
73 | # undef fputc | ||
74 | # define fputc(x,y) fputc_unlocked (x,y) | ||
75 | # else | ||
76 | # define fputc_unlocked(x,y) fputc (x,y) | ||
77 | # endif | ||
78 | |||
79 | # if HAVE_DECL_FPUTS_UNLOCKED | ||
80 | # undef fputs | ||
81 | # define fputs(x,y) fputs_unlocked (x,y) | ||
82 | # else | ||
83 | # define fputs_unlocked(x,y) fputs (x,y) | ||
84 | # endif | ||
85 | |||
86 | # if HAVE_DECL_FREAD_UNLOCKED | ||
87 | # undef fread | ||
88 | # define fread(w,x,y,z) fread_unlocked (w,x,y,z) | ||
89 | # else | ||
90 | # define fread_unlocked(w,x,y,z) fread (w,x,y,z) | ||
91 | # endif | ||
92 | |||
93 | # if HAVE_DECL_FWRITE_UNLOCKED | ||
94 | # undef fwrite | ||
95 | # define fwrite(w,x,y,z) fwrite_unlocked (w,x,y,z) | ||
96 | # else | ||
97 | # define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z) | ||
98 | # endif | ||
99 | |||
100 | # if HAVE_DECL_GETC_UNLOCKED | ||
101 | # undef getc | ||
102 | # define getc(x) getc_unlocked (x) | ||
103 | # else | ||
104 | # define getc_unlocked(x) getc (x) | ||
105 | # endif | ||
106 | |||
107 | # if HAVE_DECL_GETCHAR_UNLOCKED | ||
108 | # undef getchar | ||
109 | # define getchar() getchar_unlocked () | ||
110 | # else | ||
111 | # define getchar_unlocked() getchar () | ||
112 | # endif | ||
113 | |||
114 | # if HAVE_DECL_PUTC_UNLOCKED | ||
115 | # undef putc | ||
116 | # define putc(x,y) putc_unlocked (x,y) | ||
117 | # else | ||
118 | # define putc_unlocked(x,y) putc (x,y) | ||
119 | # endif | ||
120 | |||
121 | # if HAVE_DECL_PUTCHAR_UNLOCKED | ||
122 | # undef putchar | ||
123 | # define putchar(x) putchar_unlocked (x) | ||
124 | # else | ||
125 | # define putchar_unlocked(x) putchar (x) | ||
126 | # endif | ||
127 | |||
128 | # undef flockfile | ||
129 | # define flockfile(x) ((void) 0) | ||
130 | |||
131 | # undef ftrylockfile | ||
132 | # define ftrylockfile(x) 0 | ||
133 | |||
134 | # undef funlockfile | ||
135 | # define funlockfile(x) ((void) 0) | ||
136 | |||
137 | #endif /* UNLOCKED_IO_H */ |
mailbox/vasnprintf.c
deleted
100644 → 0
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 | #ifdef HAVE_CONFIG_H | ||
26 | # include <config.h> | ||
27 | #endif | ||
28 | #ifndef IN_LIBINTL | ||
29 | # include <alloca.h> | ||
30 | #endif | ||
31 | |||
32 | /* Specification. */ | ||
33 | #if WIDE_CHAR_VERSION | ||
34 | # include "vasnwprintf.h" | ||
35 | #else | ||
36 | # include "vasnprintf.h" | ||
37 | #endif | ||
38 | |||
39 | #include <stdio.h> /* snprintf(), sprintf() */ | ||
40 | #include <stdlib.h> /* abort(), malloc(), realloc(), free() */ | ||
41 | #include <string.h> /* memcpy(), strlen() */ | ||
42 | #include <errno.h> /* errno */ | ||
43 | #include <limits.h> /* CHAR_BIT */ | ||
44 | #include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */ | ||
45 | #if WIDE_CHAR_VERSION | ||
46 | # include "wprintf-parse.h" | ||
47 | #else | ||
48 | # include "printf-parse.h" | ||
49 | #endif | ||
50 | |||
51 | /* Checked size_t computations. */ | ||
52 | #include "xsize.h" | ||
53 | |||
54 | #ifdef HAVE_WCHAR_T | ||
55 | # ifdef HAVE_WCSLEN | ||
56 | # define local_wcslen wcslen | ||
57 | # else | ||
58 | /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid | ||
59 | a dependency towards this library, here is a local substitute. | ||
60 | Define this substitute only once, even if this file is included | ||
61 | twice in the same compilation unit. */ | ||
62 | # ifndef local_wcslen_defined | ||
63 | # define local_wcslen_defined 1 | ||
64 | static size_t | ||
65 | local_wcslen (const wchar_t *s) | ||
66 | { | ||
67 | const wchar_t *ptr; | ||
68 | |||
69 | for (ptr = s; *ptr != (wchar_t) 0; ptr++) | ||
70 | ; | ||
71 | return ptr - s; | ||
72 | } | ||
73 | # endif | ||
74 | # endif | ||
75 | #endif | ||
76 | |||
77 | #if WIDE_CHAR_VERSION | ||
78 | # define VASNPRINTF vasnwprintf | ||
79 | # define CHAR_T wchar_t | ||
80 | # define DIRECTIVE wchar_t_directive | ||
81 | # define DIRECTIVES wchar_t_directives | ||
82 | # define PRINTF_PARSE wprintf_parse | ||
83 | # define USE_SNPRINTF 1 | ||
84 | # if HAVE_DECL__SNWPRINTF | ||
85 | /* On Windows, the function swprintf() has a different signature than | ||
86 | on Unix; we use the _snwprintf() function instead. */ | ||
87 | # define SNPRINTF _snwprintf | ||
88 | # else | ||
89 | /* Unix. */ | ||
90 | # define SNPRINTF swprintf | ||
91 | # endif | ||
92 | #else | ||
93 | # define VASNPRINTF vasnprintf | ||
94 | # define CHAR_T char | ||
95 | # define DIRECTIVE char_directive | ||
96 | # define DIRECTIVES char_directives | ||
97 | # define PRINTF_PARSE printf_parse | ||
98 | # define USE_SNPRINTF (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) | ||
99 | # if HAVE_DECL__SNPRINTF | ||
100 | /* Windows. */ | ||
101 | # define SNPRINTF _snprintf | ||
102 | # else | ||
103 | /* Unix. */ | ||
104 | # define SNPRINTF snprintf | ||
105 | # endif | ||
106 | #endif | ||
107 | |||
108 | CHAR_T * | ||
109 | VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list args) | ||
110 | { | ||
111 | DIRECTIVES d; | ||
112 | arguments a; | ||
113 | |||
114 | if (PRINTF_PARSE (format, &d, &a) < 0) | ||
115 | { | ||
116 | errno = EINVAL; | ||
117 | return NULL; | ||
118 | } | ||
119 | |||
120 | #define CLEANUP() \ | ||
121 | free (d.dir); \ | ||
122 | if (a.arg) \ | ||
123 | free (a.arg); | ||
124 | |||
125 | if (printf_fetchargs (args, &a) < 0) | ||
126 | { | ||
127 | CLEANUP (); | ||
128 | errno = EINVAL; | ||
129 | return NULL; | ||
130 | } | ||
131 | |||
132 | { | ||
133 | size_t buf_neededlength; | ||
134 | CHAR_T *buf; | ||
135 | CHAR_T *buf_malloced; | ||
136 | const CHAR_T *cp; | ||
137 | size_t i; | ||
138 | DIRECTIVE *dp; | ||
139 | /* Output string accumulator. */ | ||
140 | CHAR_T *result; | ||
141 | size_t allocated; | ||
142 | size_t length; | ||
143 | |||
144 | /* Allocate a small buffer that will hold a directive passed to | ||
145 | sprintf or snprintf. */ | ||
146 | buf_neededlength = | ||
147 | xsum4 (7, d.max_width_length, d.max_precision_length, 6); | ||
148 | #if HAVE_ALLOCA | ||
149 | if (buf_neededlength < 4000 / sizeof (CHAR_T)) | ||
150 | { | ||
151 | buf = (CHAR_T *) alloca (buf_neededlength * sizeof (CHAR_T)); | ||
152 | buf_malloced = NULL; | ||
153 | } | ||
154 | else | ||
155 | #endif | ||
156 | { | ||
157 | size_t buf_memsize = xtimes (buf_neededlength, sizeof (CHAR_T)); | ||
158 | if (size_overflow_p (buf_memsize)) | ||
159 | goto out_of_memory_1; | ||
160 | buf = (CHAR_T *) malloc (buf_memsize); | ||
161 | if (buf == NULL) | ||
162 | goto out_of_memory_1; | ||
163 | buf_malloced = buf; | ||
164 | } | ||
165 | |||
166 | if (resultbuf != NULL) | ||
167 | { | ||
168 | result = resultbuf; | ||
169 | allocated = *lengthp; | ||
170 | } | ||
171 | else | ||
172 | { | ||
173 | result = NULL; | ||
174 | allocated = 0; | ||
175 | } | ||
176 | length = 0; | ||
177 | /* Invariants: | ||
178 | result is either == resultbuf or == NULL or malloc-allocated. | ||
179 | If length > 0, then result != NULL. */ | ||
180 | |||
181 | /* Ensures that allocated >= needed. Aborts through a jump to | ||
182 | out_of_memory if needed is SIZE_MAX or otherwise too big. */ | ||
183 | #define ENSURE_ALLOCATION(needed) \ | ||
184 | if ((needed) > allocated) \ | ||
185 | { \ | ||
186 | size_t memory_size; \ | ||
187 | CHAR_T *memory; \ | ||
188 | \ | ||
189 | allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \ | ||
190 | if ((needed) > allocated) \ | ||
191 | allocated = (needed); \ | ||
192 | memory_size = xtimes (allocated, sizeof (CHAR_T)); \ | ||
193 | if (size_overflow_p (memory_size)) \ | ||
194 | goto out_of_memory; \ | ||
195 | if (result == resultbuf || result == NULL) \ | ||
196 | memory = (CHAR_T *) malloc (memory_size); \ | ||
197 | else \ | ||
198 | memory = (CHAR_T *) realloc (result, memory_size); \ | ||
199 | if (memory == NULL) \ | ||
200 | goto out_of_memory; \ | ||
201 | if (result == resultbuf && length > 0) \ | ||
202 | memcpy (memory, result, length * sizeof (CHAR_T)); \ | ||
203 | result = memory; \ | ||
204 | } | ||
205 | |||
206 | for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++) | ||
207 | { | ||
208 | if (cp != dp->dir_start) | ||
209 | { | ||
210 | size_t n = dp->dir_start - cp; | ||
211 | size_t augmented_length = xsum (length, n); | ||
212 | |||
213 | ENSURE_ALLOCATION (augmented_length); | ||
214 | memcpy (result + length, cp, n * sizeof (CHAR_T)); | ||
215 | length = augmented_length; | ||
216 | } | ||
217 | if (i == d.count) | ||
218 | break; | ||
219 | |||
220 | /* Execute a single directive. */ | ||
221 | if (dp->conversion == '%') | ||
222 | { | ||
223 | size_t augmented_length; | ||
224 | |||
225 | if (!(dp->arg_index == ARG_NONE)) | ||
226 | abort (); | ||
227 | augmented_length = xsum (length, 1); | ||
228 | ENSURE_ALLOCATION (augmented_length); | ||
229 | result[length] = '%'; | ||
230 | length = augmented_length; | ||
231 | } | ||
232 | else | ||
233 | { | ||
234 | if (!(dp->arg_index != ARG_NONE)) | ||
235 | abort (); | ||
236 | |||
237 | if (dp->conversion == 'n') | ||
238 | { | ||
239 | switch (a.arg[dp->arg_index].type) | ||
240 | { | ||
241 | case TYPE_COUNT_SCHAR_POINTER: | ||
242 | *a.arg[dp->arg_index].a.a_count_schar_pointer = length; | ||
243 | break; | ||
244 | case TYPE_COUNT_SHORT_POINTER: | ||
245 | *a.arg[dp->arg_index].a.a_count_short_pointer = length; | ||
246 | break; | ||
247 | case TYPE_COUNT_INT_POINTER: | ||
248 | *a.arg[dp->arg_index].a.a_count_int_pointer = length; | ||
249 | break; | ||
250 | case TYPE_COUNT_LONGINT_POINTER: | ||
251 | *a.arg[dp->arg_index].a.a_count_longint_pointer = length; | ||
252 | break; | ||
253 | #ifdef HAVE_LONG_LONG | ||
254 | case TYPE_COUNT_LONGLONGINT_POINTER: | ||
255 | *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length; | ||
256 | break; | ||
257 | #endif | ||
258 | default: | ||
259 | abort (); | ||
260 | } | ||
261 | } | ||
262 | else | ||
263 | { | ||
264 | arg_type type = a.arg[dp->arg_index].type; | ||
265 | CHAR_T *p; | ||
266 | unsigned int prefix_count; | ||
267 | int prefixes[2]; | ||
268 | #if !USE_SNPRINTF | ||
269 | size_t tmp_length; | ||
270 | CHAR_T tmpbuf[700]; | ||
271 | CHAR_T *tmp; | ||
272 | |||
273 | /* Allocate a temporary buffer of sufficient size for calling | ||
274 | sprintf. */ | ||
275 | { | ||
276 | size_t width; | ||
277 | size_t precision; | ||
278 | |||
279 | width = 0; | ||
280 | if (dp->width_start != dp->width_end) | ||
281 | { | ||
282 | if (dp->width_arg_index != ARG_NONE) | ||
283 | { | ||
284 | int arg; | ||
285 | |||
286 | if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) | ||
287 | abort (); | ||
288 | arg = a.arg[dp->width_arg_index].a.a_int; | ||
289 | width = (arg < 0 ? (unsigned int) (-arg) : arg); | ||
290 | } | ||
291 | else | ||
292 | { | ||
293 | const CHAR_T *digitp = dp->width_start; | ||
294 | |||
295 | do | ||
296 | width = xsum (xtimes (width, 10), *digitp++ - '0'); | ||
297 | while (digitp != dp->width_end); | ||
298 | } | ||
299 | } | ||
300 | |||
301 | precision = 6; | ||
302 | if (dp->precision_start != dp->precision_end) | ||
303 | { | ||
304 | if (dp->precision_arg_index != ARG_NONE) | ||
305 | { | ||
306 | int arg; | ||
307 | |||
308 | if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) | ||
309 | abort (); | ||
310 | arg = a.arg[dp->precision_arg_index].a.a_int; | ||
311 | precision = (arg < 0 ? 0 : arg); | ||
312 | } | ||
313 | else | ||
314 | { | ||
315 | const CHAR_T *digitp = dp->precision_start + 1; | ||
316 | |||
317 | precision = 0; | ||
318 | while (digitp != dp->precision_end) | ||
319 | precision = xsum (xtimes (precision, 10), *digitp++ - '0'); | ||
320 | } | ||
321 | } | ||
322 | |||
323 | switch (dp->conversion) | ||
324 | { | ||
325 | |||
326 | case 'd': case 'i': case 'u': | ||
327 | # ifdef HAVE_LONG_LONG | ||
328 | if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) | ||
329 | tmp_length = | ||
330 | (unsigned int) (sizeof (unsigned long long) * CHAR_BIT | ||
331 | * 0.30103 /* binary -> decimal */ | ||
332 | ) | ||
333 | + 1; /* turn floor into ceil */ | ||
334 | else | ||
335 | # endif | ||
336 | if (type == TYPE_LONGINT || type == TYPE_ULONGINT) | ||
337 | tmp_length = | ||
338 | (unsigned int) (sizeof (unsigned long) * CHAR_BIT | ||
339 | * 0.30103 /* binary -> decimal */ | ||
340 | ) | ||
341 | + 1; /* turn floor into ceil */ | ||
342 | else | ||
343 | tmp_length = | ||
344 | (unsigned int) (sizeof (unsigned int) * CHAR_BIT | ||
345 | * 0.30103 /* binary -> decimal */ | ||
346 | ) | ||
347 | + 1; /* turn floor into ceil */ | ||
348 | if (tmp_length < precision) | ||
349 | tmp_length = precision; | ||
350 | /* Multiply by 2, as an estimate for FLAG_GROUP. */ | ||
351 | tmp_length = xsum (tmp_length, tmp_length); | ||
352 | /* Add 1, to account for a leading sign. */ | ||
353 | tmp_length = xsum (tmp_length, 1); | ||
354 | break; | ||
355 | |||
356 | case 'o': | ||
357 | # ifdef HAVE_LONG_LONG | ||
358 | if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) | ||
359 | tmp_length = | ||
360 | (unsigned int) (sizeof (unsigned long long) * CHAR_BIT | ||
361 | * 0.333334 /* binary -> octal */ | ||
362 | ) | ||
363 | + 1; /* turn floor into ceil */ | ||
364 | else | ||
365 | # endif | ||
366 | if (type == TYPE_LONGINT || type == TYPE_ULONGINT) | ||
367 | tmp_length = | ||
368 | (unsigned int) (sizeof (unsigned long) * CHAR_BIT | ||
369 | * 0.333334 /* binary -> octal */ | ||
370 | ) | ||
371 | + 1; /* turn floor into ceil */ | ||
372 | else | ||
373 | tmp_length = | ||
374 | (unsigned int) (sizeof (unsigned int) * CHAR_BIT | ||
375 | * 0.333334 /* binary -> octal */ | ||
376 | ) | ||
377 | + 1; /* turn floor into ceil */ | ||
378 | if (tmp_length < precision) | ||
379 | tmp_length = precision; | ||
380 | /* Add 1, to account for a leading sign. */ | ||
381 | tmp_length = xsum (tmp_length, 1); | ||
382 | break; | ||
383 | |||
384 | case 'x': case 'X': | ||
385 | # ifdef HAVE_LONG_LONG | ||
386 | if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) | ||
387 | tmp_length = | ||
388 | (unsigned int) (sizeof (unsigned long long) * CHAR_BIT | ||
389 | * 0.25 /* binary -> hexadecimal */ | ||
390 | ) | ||
391 | + 1; /* turn floor into ceil */ | ||
392 | else | ||
393 | # endif | ||
394 | if (type == TYPE_LONGINT || type == TYPE_ULONGINT) | ||
395 | tmp_length = | ||
396 | (unsigned int) (sizeof (unsigned long) * CHAR_BIT | ||
397 | * 0.25 /* binary -> hexadecimal */ | ||
398 | ) | ||
399 | + 1; /* turn floor into ceil */ | ||
400 | else | ||
401 | tmp_length = | ||
402 | (unsigned int) (sizeof (unsigned int) * CHAR_BIT | ||
403 | * 0.25 /* binary -> hexadecimal */ | ||
404 | ) | ||
405 | + 1; /* turn floor into ceil */ | ||
406 | if (tmp_length < precision) | ||
407 | tmp_length = precision; | ||
408 | /* Add 2, to account for a leading sign or alternate form. */ | ||
409 | tmp_length = xsum (tmp_length, 2); | ||
410 | break; | ||
411 | |||
412 | case 'f': case 'F': | ||
413 | # ifdef HAVE_LONG_DOUBLE | ||
414 | if (type == TYPE_LONGDOUBLE) | ||
415 | tmp_length = | ||
416 | (unsigned int) (LDBL_MAX_EXP | ||
417 | * 0.30103 /* binary -> decimal */ | ||
418 | * 2 /* estimate for FLAG_GROUP */ | ||
419 | ) | ||
420 | + 1 /* turn floor into ceil */ | ||
421 | + 10; /* sign, decimal point etc. */ | ||
422 | else | ||
423 | # endif | ||
424 | tmp_length = | ||
425 | (unsigned int) (DBL_MAX_EXP | ||
426 | * 0.30103 /* binary -> decimal */ | ||
427 | * 2 /* estimate for FLAG_GROUP */ | ||
428 | ) | ||
429 | + 1 /* turn floor into ceil */ | ||
430 | + 10; /* sign, decimal point etc. */ | ||
431 | tmp_length = xsum (tmp_length, precision); | ||
432 | break; | ||
433 | |||
434 | case 'e': case 'E': case 'g': case 'G': | ||
435 | case 'a': case 'A': | ||
436 | tmp_length = | ||
437 | 12; /* sign, decimal point, exponent etc. */ | ||
438 | tmp_length = xsum (tmp_length, precision); | ||
439 | break; | ||
440 | |||
441 | case 'c': | ||
442 | # if defined HAVE_WINT_T && !WIDE_CHAR_VERSION | ||
443 | if (type == TYPE_WIDE_CHAR) | ||
444 | tmp_length = MB_CUR_MAX; | ||
445 | else | ||
446 | # endif | ||
447 | tmp_length = 1; | ||
448 | break; | ||
449 | |||
450 | case 's': | ||
451 | # ifdef HAVE_WCHAR_T | ||
452 | if (type == TYPE_WIDE_STRING) | ||
453 | { | ||
454 | tmp_length = | ||
455 | local_wcslen (a.arg[dp->arg_index].a.a_wide_string); | ||
456 | |||
457 | # if !WIDE_CHAR_VERSION | ||
458 | tmp_length = xtimes (tmp_length, MB_CUR_MAX); | ||
459 | # endif | ||
460 | } | ||
461 | else | ||
462 | # endif | ||
463 | tmp_length = strlen (a.arg[dp->arg_index].a.a_string); | ||
464 | break; | ||
465 | |||
466 | case 'p': | ||
467 | tmp_length = | ||
468 | (unsigned int) (sizeof (void *) * CHAR_BIT | ||
469 | * 0.25 /* binary -> hexadecimal */ | ||
470 | ) | ||
471 | + 1 /* turn floor into ceil */ | ||
472 | + 2; /* account for leading 0x */ | ||
473 | break; | ||
474 | |||
475 | default: | ||
476 | abort (); | ||
477 | } | ||
478 | |||
479 | if (tmp_length < width) | ||
480 | tmp_length = width; | ||
481 | |||
482 | tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ | ||
483 | } | ||
484 | |||
485 | if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T)) | ||
486 | tmp = tmpbuf; | ||
487 | else | ||
488 | { | ||
489 | size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T)); | ||
490 | |||
491 | if (size_overflow_p (tmp_memsize)) | ||
492 | /* Overflow, would lead to out of memory. */ | ||
493 | goto out_of_memory; | ||
494 | tmp = (CHAR_T *) malloc (tmp_memsize); | ||
495 | if (tmp == NULL) | ||
496 | /* Out of memory. */ | ||
497 | goto out_of_memory; | ||
498 | } | ||
499 | #endif | ||
500 | |||
501 | /* Construct the format string for calling snprintf or | ||
502 | sprintf. */ | ||
503 | p = buf; | ||
504 | *p++ = '%'; | ||
505 | if (dp->flags & FLAG_GROUP) | ||
506 | *p++ = '\''; | ||
507 | if (dp->flags & FLAG_LEFT) | ||
508 | *p++ = '-'; | ||
509 | if (dp->flags & FLAG_SHOWSIGN) | ||
510 | *p++ = '+'; | ||
511 | if (dp->flags & FLAG_SPACE) | ||
512 | *p++ = ' '; | ||
513 | if (dp->flags & FLAG_ALT) | ||
514 | *p++ = '#'; | ||
515 | if (dp->flags & FLAG_ZERO) | ||
516 | *p++ = '0'; | ||
517 | if (dp->width_start != dp->width_end) | ||
518 | { | ||
519 | size_t n = dp->width_end - dp->width_start; | ||
520 | memcpy (p, dp->width_start, n * sizeof (CHAR_T)); | ||
521 | p += n; | ||
522 | } | ||
523 | if (dp->precision_start != dp->precision_end) | ||
524 | { | ||
525 | size_t n = dp->precision_end - dp->precision_start; | ||
526 | memcpy (p, dp->precision_start, n * sizeof (CHAR_T)); | ||
527 | p += n; | ||
528 | } | ||
529 | |||
530 | switch (type) | ||
531 | { | ||
532 | #ifdef HAVE_LONG_LONG | ||
533 | case TYPE_LONGLONGINT: | ||
534 | case TYPE_ULONGLONGINT: | ||
535 | *p++ = 'l'; | ||
536 | /*FALLTHROUGH*/ | ||
537 | #endif | ||
538 | case TYPE_LONGINT: | ||
539 | case TYPE_ULONGINT: | ||
540 | #ifdef HAVE_WINT_T | ||
541 | case TYPE_WIDE_CHAR: | ||
542 | #endif | ||
543 | #ifdef HAVE_WCHAR_T | ||
544 | case TYPE_WIDE_STRING: | ||
545 | #endif | ||
546 | *p++ = 'l'; | ||
547 | break; | ||
548 | #ifdef HAVE_LONG_DOUBLE | ||
549 | case TYPE_LONGDOUBLE: | ||
550 | *p++ = 'L'; | ||
551 | break; | ||
552 | #endif | ||
553 | default: | ||
554 | break; | ||
555 | } | ||
556 | *p = dp->conversion; | ||
557 | #if USE_SNPRINTF | ||
558 | p[1] = '%'; | ||
559 | p[2] = 'n'; | ||
560 | p[3] = '\0'; | ||
561 | #else | ||
562 | p[1] = '\0'; | ||
563 | #endif | ||
564 | |||
565 | /* Construct the arguments for calling snprintf or sprintf. */ | ||
566 | prefix_count = 0; | ||
567 | if (dp->width_arg_index != ARG_NONE) | ||
568 | { | ||
569 | if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) | ||
570 | abort (); | ||
571 | prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int; | ||
572 | } | ||
573 | if (dp->precision_arg_index != ARG_NONE) | ||
574 | { | ||
575 | if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) | ||
576 | abort (); | ||
577 | prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int; | ||
578 | } | ||
579 | |||
580 | #if USE_SNPRINTF | ||
581 | /* Prepare checking whether snprintf returns the count | ||
582 | via %n. */ | ||
583 | ENSURE_ALLOCATION (xsum (length, 1)); | ||
584 | result[length] = '\0'; | ||
585 | #endif | ||
586 | |||
587 | for (;;) | ||
588 | { | ||
589 | size_t maxlen; | ||
590 | int count; | ||
591 | int retcount; | ||
592 | |||
593 | maxlen = allocated - length; | ||
594 | count = -1; | ||
595 | retcount = 0; | ||
596 | |||
597 | #if USE_SNPRINTF | ||
598 | # define SNPRINTF_BUF(arg) \ | ||
599 | switch (prefix_count) \ | ||
600 | { \ | ||
601 | case 0: \ | ||
602 | retcount = SNPRINTF (result + length, maxlen, buf, \ | ||
603 | arg, &count); \ | ||
604 | break; \ | ||
605 | case 1: \ | ||
606 | retcount = SNPRINTF (result + length, maxlen, buf, \ | ||
607 | prefixes[0], arg, &count); \ | ||
608 | break; \ | ||
609 | case 2: \ | ||
610 | retcount = SNPRINTF (result + length, maxlen, buf, \ | ||
611 | prefixes[0], prefixes[1], arg, \ | ||
612 | &count); \ | ||
613 | break; \ | ||
614 | default: \ | ||
615 | abort (); \ | ||
616 | } | ||
617 | #else | ||
618 | # define SNPRINTF_BUF(arg) \ | ||
619 | switch (prefix_count) \ | ||
620 | { \ | ||
621 | case 0: \ | ||
622 | count = sprintf (tmp, buf, arg); \ | ||
623 | break; \ | ||
624 | case 1: \ | ||
625 | count = sprintf (tmp, buf, prefixes[0], arg); \ | ||
626 | break; \ | ||
627 | case 2: \ | ||
628 | count = sprintf (tmp, buf, prefixes[0], prefixes[1],\ | ||
629 | arg); \ | ||
630 | break; \ | ||
631 | default: \ | ||
632 | abort (); \ | ||
633 | } | ||
634 | #endif | ||
635 | |||
636 | switch (type) | ||
637 | { | ||
638 | case TYPE_SCHAR: | ||
639 | { | ||
640 | int arg = a.arg[dp->arg_index].a.a_schar; | ||
641 | SNPRINTF_BUF (arg); | ||
642 | } | ||
643 | break; | ||
644 | case TYPE_UCHAR: | ||
645 | { | ||
646 | unsigned int arg = a.arg[dp->arg_index].a.a_uchar; | ||
647 | SNPRINTF_BUF (arg); | ||
648 | } | ||
649 | break; | ||
650 | case TYPE_SHORT: | ||
651 | { | ||
652 | int arg = a.arg[dp->arg_index].a.a_short; | ||
653 | SNPRINTF_BUF (arg); | ||
654 | } | ||
655 | break; | ||
656 | case TYPE_USHORT: | ||
657 | { | ||
658 | unsigned int arg = a.arg[dp->arg_index].a.a_ushort; | ||
659 | SNPRINTF_BUF (arg); | ||
660 | } | ||
661 | break; | ||
662 | case TYPE_INT: | ||
663 | { | ||
664 | int arg = a.arg[dp->arg_index].a.a_int; | ||
665 | SNPRINTF_BUF (arg); | ||
666 | } | ||
667 | break; | ||
668 | case TYPE_UINT: | ||
669 | { | ||
670 | unsigned int arg = a.arg[dp->arg_index].a.a_uint; | ||
671 | SNPRINTF_BUF (arg); | ||
672 | } | ||
673 | break; | ||
674 | case TYPE_LONGINT: | ||
675 | { | ||
676 | long int arg = a.arg[dp->arg_index].a.a_longint; | ||
677 | SNPRINTF_BUF (arg); | ||
678 | } | ||
679 | break; | ||
680 | case TYPE_ULONGINT: | ||
681 | { | ||
682 | unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint; | ||
683 | SNPRINTF_BUF (arg); | ||
684 | } | ||
685 | break; | ||
686 | #ifdef HAVE_LONG_LONG | ||
687 | case TYPE_LONGLONGINT: | ||
688 | { | ||
689 | long long int arg = a.arg[dp->arg_index].a.a_longlongint; | ||
690 | SNPRINTF_BUF (arg); | ||
691 | } | ||
692 | break; | ||
693 | case TYPE_ULONGLONGINT: | ||
694 | { | ||
695 | unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint; | ||
696 | SNPRINTF_BUF (arg); | ||
697 | } | ||
698 | break; | ||
699 | #endif | ||
700 | case TYPE_DOUBLE: | ||
701 | { | ||
702 | double arg = a.arg[dp->arg_index].a.a_double; | ||
703 | SNPRINTF_BUF (arg); | ||
704 | } | ||
705 | break; | ||
706 | #ifdef HAVE_LONG_DOUBLE | ||
707 | case TYPE_LONGDOUBLE: | ||
708 | { | ||
709 | long double arg = a.arg[dp->arg_index].a.a_longdouble; | ||
710 | SNPRINTF_BUF (arg); | ||
711 | } | ||
712 | break; | ||
713 | #endif | ||
714 | case TYPE_CHAR: | ||
715 | { | ||
716 | int arg = a.arg[dp->arg_index].a.a_char; | ||
717 | SNPRINTF_BUF (arg); | ||
718 | } | ||
719 | break; | ||
720 | #ifdef HAVE_WINT_T | ||
721 | case TYPE_WIDE_CHAR: | ||
722 | { | ||
723 | wint_t arg = a.arg[dp->arg_index].a.a_wide_char; | ||
724 | SNPRINTF_BUF (arg); | ||
725 | } | ||
726 | break; | ||
727 | #endif | ||
728 | case TYPE_STRING: | ||
729 | { | ||
730 | const char *arg = a.arg[dp->arg_index].a.a_string; | ||
731 | SNPRINTF_BUF (arg); | ||
732 | } | ||
733 | break; | ||
734 | #ifdef HAVE_WCHAR_T | ||
735 | case TYPE_WIDE_STRING: | ||
736 | { | ||
737 | const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string; | ||
738 | SNPRINTF_BUF (arg); | ||
739 | } | ||
740 | break; | ||
741 | #endif | ||
742 | case TYPE_POINTER: | ||
743 | { | ||
744 | void *arg = a.arg[dp->arg_index].a.a_pointer; | ||
745 | SNPRINTF_BUF (arg); | ||
746 | } | ||
747 | break; | ||
748 | default: | ||
749 | abort (); | ||
750 | } | ||
751 | |||
752 | #if USE_SNPRINTF | ||
753 | /* Portability: Not all implementations of snprintf() | ||
754 | are ISO C 99 compliant. Determine the number of | ||
755 | bytes that snprintf() has produced or would have | ||
756 | produced. */ | ||
757 | if (count >= 0) | ||
758 | { | ||
759 | /* Verify that snprintf() has NUL-terminated its | ||
760 | result. */ | ||
761 | if (count < maxlen && result[length + count] != '\0') | ||
762 | abort (); | ||
763 | /* Portability hack. */ | ||
764 | if (retcount > count) | ||
765 | count = retcount; | ||
766 | } | ||
767 | else | ||
768 | { | ||
769 | /* snprintf() doesn't understand the '%n' | ||
770 | directive. */ | ||
771 | if (p[1] != '\0') | ||
772 | { | ||
773 | /* Don't use the '%n' directive; instead, look | ||
774 | at the snprintf() return value. */ | ||
775 | p[1] = '\0'; | ||
776 | continue; | ||
777 | } | ||
778 | else | ||
779 | { | ||
780 | /* Look at the snprintf() return value. */ | ||
781 | if (retcount < 0) | ||
782 | { | ||
783 | /* HP-UX 10.20 snprintf() is doubly deficient: | ||
784 | It doesn't understand the '%n' directive, | ||
785 | *and* it returns -1 (rather than the length | ||
786 | that would have been required) when the | ||
787 | buffer is too small. */ | ||
788 | size_t bigger_need = | ||
789 | xsum (xtimes (allocated, 2), 12); | ||
790 | ENSURE_ALLOCATION (bigger_need); | ||
791 | continue; | ||
792 | } | ||
793 | else | ||
794 | count = retcount; | ||
795 | } | ||
796 | } | ||
797 | #endif | ||
798 | |||
799 | /* Attempt to handle failure. */ | ||
800 | if (count < 0) | ||
801 | { | ||
802 | if (!(result == resultbuf || result == NULL)) | ||
803 | free (result); | ||
804 | if (buf_malloced != NULL) | ||
805 | free (buf_malloced); | ||
806 | CLEANUP (); | ||
807 | errno = EINVAL; | ||
808 | return NULL; | ||
809 | } | ||
810 | |||
811 | #if !USE_SNPRINTF | ||
812 | if (count >= tmp_length) | ||
813 | /* tmp_length was incorrectly calculated - fix the | ||
814 | code above! */ | ||
815 | abort (); | ||
816 | #endif | ||
817 | |||
818 | /* Make room for the result. */ | ||
819 | if (count >= maxlen) | ||
820 | { | ||
821 | /* Need at least count bytes. But allocate | ||
822 | proportionally, to avoid looping eternally if | ||
823 | snprintf() reports a too small count. */ | ||
824 | size_t n = | ||
825 | xmax (xsum (length, count), xtimes (allocated, 2)); | ||
826 | |||
827 | ENSURE_ALLOCATION (n); | ||
828 | #if USE_SNPRINTF | ||
829 | continue; | ||
830 | #endif | ||
831 | } | ||
832 | |||
833 | #if USE_SNPRINTF | ||
834 | /* The snprintf() result did fit. */ | ||
835 | #else | ||
836 | /* Append the sprintf() result. */ | ||
837 | memcpy (result + length, tmp, count * sizeof (CHAR_T)); | ||
838 | if (tmp != tmpbuf) | ||
839 | free (tmp); | ||
840 | #endif | ||
841 | |||
842 | length += count; | ||
843 | break; | ||
844 | } | ||
845 | } | ||
846 | } | ||
847 | } | ||
848 | |||
849 | /* Add the final NUL. */ | ||
850 | ENSURE_ALLOCATION (xsum (length, 1)); | ||
851 | result[length] = '\0'; | ||
852 | |||
853 | if (result != resultbuf && length + 1 < allocated) | ||
854 | { | ||
855 | /* Shrink the allocated memory if possible. */ | ||
856 | CHAR_T *memory; | ||
857 | |||
858 | memory = (CHAR_T *) realloc (result, (length + 1) * sizeof (CHAR_T)); | ||
859 | if (memory != NULL) | ||
860 | result = memory; | ||
861 | } | ||
862 | |||
863 | if (buf_malloced != NULL) | ||
864 | free (buf_malloced); | ||
865 | CLEANUP (); | ||
866 | *lengthp = length; | ||
867 | /* Note that we can produce a big string of a length > INT_MAX. POSIX | ||
868 | says that snprintf() fails with errno = EOVERFLOW in this case, but | ||
869 | that's only because snprintf() returns an 'int'. This function does | ||
870 | not have this limitation. */ | ||
871 | return result; | ||
872 | |||
873 | out_of_memory: | ||
874 | if (!(result == resultbuf || result == NULL)) | ||
875 | free (result); | ||
876 | if (buf_malloced != NULL) | ||
877 | free (buf_malloced); | ||
878 | out_of_memory_1: | ||
879 | CLEANUP (); | ||
880 | errno = ENOMEM; | ||
881 | return NULL; | ||
882 | } | ||
883 | } | ||
884 | |||
885 | #undef SNPRINTF | ||
886 | #undef USE_SNPRINTF | ||
887 | #undef PRINTF_PARSE | ||
888 | #undef DIRECTIVES | ||
889 | #undef DIRECTIVE | ||
890 | #undef CHAR_T | ||
891 | #undef VASNPRINTF |
mailbox/vasnprintf.h
deleted
100644 → 0
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 | ||
41 | extern "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 | */ | ||
68 | extern char * asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...) | ||
69 | __attribute__ ((__format__ (__printf__, 3, 4))); | ||
70 | extern 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 */ |
mailbox/vsnprintf.c
deleted
100644 → 0
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. */ | ||
45 | int | ||
46 | vsnprintf (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 | } |
mailbox/vsnprintf.h
deleted
100644 → 0
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 | ||
28 | int vsnprintf (char *str, size_t size, const char *format, va_list args); | ||
29 | #endif | ||
30 | |||
31 | #endif /* VSNPRINTF_H */ |
mailbox/wcwidth.h
deleted
100644 → 0
1 | /* Determine the number of screen columns needed for a character. | ||
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_WCWIDTH_H | ||
19 | #define _gl_WCWIDTH_H | ||
20 | |||
21 | #if HAVE_WCHAR_T | ||
22 | |||
23 | /* Get wcwidth if available, along with wchar_t. */ | ||
24 | # if HAVE_WCHAR_H | ||
25 | /* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before | ||
26 | <wchar.h>. | ||
27 | BSD/OS 4.1 has a bug: <stdio.h> and <time.h> must be included before | ||
28 | <wchar.h>. */ | ||
29 | # include <stdio.h> | ||
30 | # include <time.h> | ||
31 | # include <wchar.h> | ||
32 | # endif | ||
33 | |||
34 | /* Get iswprint. */ | ||
35 | # if HAVE_WCTYPE_H | ||
36 | # include <wctype.h> | ||
37 | # endif | ||
38 | # if !defined iswprint && !HAVE_ISWPRINT | ||
39 | static inline int | ||
40 | iswprint (wint_t wc) | ||
41 | { | ||
42 | return (wc >= 0 && wc < 128 | ||
43 | ? wc >= ' ' && wc <= '~' | ||
44 | : 1); | ||
45 | } | ||
46 | # define iswprint iswprint | ||
47 | # endif | ||
48 | |||
49 | # ifndef HAVE_DECL_WCWIDTH | ||
50 | "this configure-time declaration test was not run" | ||
51 | # endif | ||
52 | # ifndef wcwidth | ||
53 | # if !HAVE_WCWIDTH | ||
54 | |||
55 | /* wcwidth doesn't exist, so assume all printable characters have | ||
56 | width 1. */ | ||
57 | static inline int | ||
58 | wcwidth (wchar_t wc) | ||
59 | { | ||
60 | return wc == 0 ? 0 : iswprint (wc) ? 1 : -1; | ||
61 | } | ||
62 | |||
63 | # elif !HAVE_DECL_WCWIDTH | ||
64 | |||
65 | /* wcwidth exists but is not declared. */ | ||
66 | extern | ||
67 | # ifdef __cplusplus | ||
68 | "C" | ||
69 | # endif | ||
70 | int wcwidth (int /* actually wchar_t */); | ||
71 | |||
72 | # endif | ||
73 | # endif | ||
74 | |||
75 | #endif /* HAVE_WCHAR_H */ | ||
76 | |||
77 | #endif /* _gl_WCWIDTH_H */ |
mailbox/xsize.h
deleted
100644 → 0
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. */ | ||
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