Mercurial > hg > octave-kai > gnulib-hg
annotate lib/getndelim2.c @ 8582:88177595d847
Tweak last patch: Sync with gettext.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Thu, 29 Mar 2007 22:34:33 +0000 |
parents | 84cd79e074c1 |
children | bbbbbf4cd1c5 |
rev | line source |
---|---|
4463 | 1 /* getndelim2 - Read a line from a stream, stopping at one of 2 delimiters, |
2 with bounded memory allocation. | |
4460 | 3 |
7162
19c2e5121b2f
Add and change modules to make it easier for coreutils to use
Paul Eggert <eggert@cs.ucla.edu>
parents:
6259
diff
changeset
|
4 Copyright (C) 1993, 1996, 1997, 1998, 2000, 2003, 2004, 2006 Free |
19c2e5121b2f
Add and change modules to make it easier for coreutils to use
Paul Eggert <eggert@cs.ucla.edu>
parents:
6259
diff
changeset
|
5 Software Foundation, Inc. |
4460 | 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, | |
5848
a48fb0e98c8c
*** empty log message ***
Paul Eggert <eggert@cs.ucla.edu>
parents:
5318
diff
changeset
|
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ |
4460 | 20 |
4463 | 21 /* Originally written by Jan Brittenson, bson@gnu.ai.mit.edu. */ |
22 | |
7302
8a1a9361108c
* _fpending.c: Include <config.h> unconditionally, since we no
Paul Eggert <eggert@cs.ucla.edu>
parents:
7162
diff
changeset
|
23 #include <config.h> |
4463 | 24 |
25 #include "getndelim2.h" | |
26 | |
4650 | 27 #include <stdlib.h> |
5102
d39dc0b72f5b
* getndelim2.c: Include stddef.h, for ptrdiff_t.
Paul Eggert <eggert@cs.ucla.edu>
parents:
5062
diff
changeset
|
28 #include <stddef.h> |
4460 | 29 |
5318
7c24a825b51d
Remove dependencies on unlocked-io.
Paul Eggert <eggert@cs.ucla.edu>
parents:
5102
diff
changeset
|
30 #if USE_UNLOCKED_IO |
7c24a825b51d
Remove dependencies on unlocked-io.
Paul Eggert <eggert@cs.ucla.edu>
parents:
5102
diff
changeset
|
31 # include "unlocked-io.h" |
7c24a825b51d
Remove dependencies on unlocked-io.
Paul Eggert <eggert@cs.ucla.edu>
parents:
5102
diff
changeset
|
32 #endif |
4460 | 33 |
5062
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
34 #include <limits.h> |
7162
19c2e5121b2f
Add and change modules to make it easier for coreutils to use
Paul Eggert <eggert@cs.ucla.edu>
parents:
6259
diff
changeset
|
35 #include <stdint.h> |
5062
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
36 |
7538
a75213853379
Make getndelim2 compile on mingw.
Bruno Haible <bruno@clisp.org>
parents:
7302
diff
changeset
|
37 #ifndef SSIZE_MAX |
7539
84cd79e074c1
* lib/getndelim2.c (SSIZE_MAX): Use same defn that getdelim.c
Paul Eggert <eggert@cs.ucla.edu>
parents:
7538
diff
changeset
|
38 # define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) |
7538
a75213853379
Make getndelim2 compile on mingw.
Bruno Haible <bruno@clisp.org>
parents:
7302
diff
changeset
|
39 #endif |
a75213853379
Make getndelim2 compile on mingw.
Bruno Haible <bruno@clisp.org>
parents:
7302
diff
changeset
|
40 |
5062
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
41 /* The maximum value that getndelim2 can return without suffering from |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
42 overflow problems, either internally (because of pointer |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
43 subtraction overflow) or due to the API (because of ssize_t). */ |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
44 #define GETNDELIM2_MAXIMUM (PTRDIFF_MAX < SSIZE_MAX ? PTRDIFF_MAX : SSIZE_MAX) |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
45 |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
46 /* Try to add at least this many bytes when extending the buffer. |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
47 MIN_CHUNK must be no greater than GETNDELIM2_MAXIMUM. */ |
4460 | 48 #define MIN_CHUNK 64 |
49 | |
4463 | 50 ssize_t |
5062
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
51 getndelim2 (char **lineptr, size_t *linesize, size_t offset, size_t nmax, |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
52 int delim1, int delim2, FILE *stream) |
4460 | 53 { |
5062
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
54 size_t nbytes_avail; /* Allocated but unused bytes in *LINEPTR. */ |
4460 | 55 char *read_pos; /* Where we're reading into *LINEPTR. */ |
5062
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
56 ssize_t bytes_stored = -1; |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
57 char *ptr = *lineptr; |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
58 size_t size = *linesize; |
4460 | 59 |
5062
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
60 if (!ptr) |
4460 | 61 { |
5062
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
62 size = nmax < MIN_CHUNK ? nmax : MIN_CHUNK; |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
63 ptr = malloc (size); |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
64 if (!ptr) |
4460 | 65 return -1; |
66 } | |
67 | |
5062
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
68 if (size < offset) |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
69 goto done; |
4460 | 70 |
5062
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
71 nbytes_avail = size - offset; |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
72 read_pos = ptr + offset; |
4460 | 73 |
5062
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
74 if (nbytes_avail == 0 && nmax <= size) |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
75 goto done; |
4460 | 76 |
77 for (;;) | |
78 { | |
5062
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
79 /* Here always ptr + size == read_pos + nbytes_avail. */ |
4460 | 80 |
5062
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
81 int c; |
4460 | 82 |
5062
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
83 /* We always want at least one byte left in the buffer, since we |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
84 always (unless we get an error while reading the first byte) |
4460 | 85 NUL-terminate the line buffer. */ |
86 | |
5062
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
87 if (nbytes_avail < 2 && size < nmax) |
4460 | 88 { |
5062
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
89 size_t newsize = size < MIN_CHUNK ? size + MIN_CHUNK : 2 * size; |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
90 char *newptr; |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
91 |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
92 if (! (size < newsize && newsize <= nmax)) |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
93 newsize = nmax; |
4460 | 94 |
5062
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
95 if (GETNDELIM2_MAXIMUM < newsize - offset) |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
96 { |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
97 size_t newsizemax = offset + GETNDELIM2_MAXIMUM + 1; |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
98 if (size == newsizemax) |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
99 goto done; |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
100 newsize = newsizemax; |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
101 } |
4460 | 102 |
5062
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
103 nbytes_avail = newsize - (read_pos - ptr); |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
104 newptr = realloc (ptr, newsize); |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
105 if (!newptr) |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
106 goto done; |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
107 ptr = newptr; |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
108 size = newsize; |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
109 read_pos = size - nbytes_avail + ptr; |
4460 | 110 } |
111 | |
4711
37bbd4e80866
Don't trash errno when a read fails.
Paul Eggert <eggert@cs.ucla.edu>
parents:
4650
diff
changeset
|
112 c = getc (stream); |
37bbd4e80866
Don't trash errno when a read fails.
Paul Eggert <eggert@cs.ucla.edu>
parents:
4650
diff
changeset
|
113 if (c == EOF) |
4460 | 114 { |
115 /* Return partial line, if any. */ | |
5062
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
116 if (read_pos == ptr) |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
117 goto done; |
4460 | 118 else |
119 break; | |
120 } | |
121 | |
122 if (nbytes_avail >= 2) | |
123 { | |
124 *read_pos++ = c; | |
125 nbytes_avail--; | |
126 } | |
127 | |
5062
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
128 if (c == delim1 || c == delim2) |
4460 | 129 /* Return the line. */ |
130 break; | |
131 } | |
132 | |
5062
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
133 /* Done - NUL terminate and return the number of bytes read. |
4460 | 134 At this point we know that nbytes_avail >= 1. */ |
135 *read_pos = '\0'; | |
136 | |
5062
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
137 bytes_stored = read_pos - (ptr + offset); |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
138 |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
139 done: |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
140 *lineptr = ptr; |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
141 *linesize = size; |
aa119e787246
getline cleanup. This changes the getndelim2 API: both order of arguments,
Paul Eggert <eggert@cs.ucla.edu>
parents:
5049
diff
changeset
|
142 return bytes_stored; |
4460 | 143 } |