Mercurial > hg > octave-kai > gnulib-hg
annotate lib/readtokens.c @ 2886:dc65428d47a6
*** empty log message ***
author | Jim Meyering <jim@meyering.net> |
---|---|
date | Tue, 17 Oct 2000 06:45:57 +0000 |
parents | c30d7ad98237 |
children | 72422d1e9181 |
rev | line source |
---|---|
375 | 1 /* readtokens.c -- Functions for reading tokens from an input stream. |
1778
c30d7ad98237
(readtoken, readtokens): Protoize.
Jim Meyering <jim@meyering.net>
parents:
653
diff
changeset
|
2 Copyright (C) 1990-1991, 1999 Jim Meyering. |
375 | 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 | |
651
242f0fe39aa7
update FSF address in copyright
Jim Meyering <jim@meyering.net>
parents:
555
diff
changeset
|
15 along with this program; if not, write to the Free Software Foundation, |
242f0fe39aa7
update FSF address in copyright
Jim Meyering <jim@meyering.net>
parents:
555
diff
changeset
|
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
375 | 17 |
18 Written by Jim Meyering. */ | |
19 | |
20 /* This almost supercedes xreadline stuff -- using delim="\n" | |
21 gives the same functionality, except that these functions | |
22 would never return empty lines. | |
23 | |
24 To Do: | |
25 - To allow '\0' as a delimiter, I will have to change | |
26 interfaces to permit specification of delimiter-string | |
27 length. | |
28 */ | |
29 | |
30 #ifdef HAVE_CONFIG_H | |
653 | 31 # include <config.h> |
375 | 32 #endif |
33 | |
34 #include <stdio.h> | |
35 | |
36 #ifdef STDC_HEADERS | |
653 | 37 # include <stdlib.h> |
375 | 38 #endif |
39 | |
40 #if defined (STDC_HEADERS) || defined(HAVE_STRING_H) | |
653 | 41 # include <string.h> |
375 | 42 /* An ANSI string.h and pre-ANSI memory.h might conflict. */ |
653 | 43 # if !defined (STDC_HEADERS) && defined (HAVE_MEMORY_H) |
44 # include <memory.h> | |
45 # endif /* not STDC_HEADERS and HAVE_MEMORY_H */ | |
375 | 46 #else /* not STDC_HEADERS and not HAVE_STRING_H */ |
653 | 47 # include <strings.h> |
375 | 48 /* memory.h and strings.h conflict on some systems. */ |
49 #endif /* not STDC_HEADERS and not HAVE_STRING_H */ | |
50 | |
51 #include "readtokens.h" | |
477
c30155ecefad
Declare xmalloc, xrealloc rather than including xalloc.h.
Jim Meyering <jim@meyering.net>
parents:
375
diff
changeset
|
52 void *xmalloc (); |
c30155ecefad
Declare xmalloc, xrealloc rather than including xalloc.h.
Jim Meyering <jim@meyering.net>
parents:
375
diff
changeset
|
53 void *xrealloc (); |
375 | 54 |
55 #define STREQ(a,b) ((a) == (b) || ((a) && (b) && *(a) == *(b) \ | |
56 && strcmp(a, b) == 0)) | |
57 | |
58 /* Initialize a tokenbuffer. */ | |
59 | |
60 void | |
555 | 61 init_tokenbuffer (tokenbuffer) |
62 token_buffer *tokenbuffer; | |
375 | 63 { |
64 tokenbuffer->size = INITIAL_TOKEN_LENGTH; | |
65 tokenbuffer->buffer = ((char *) xmalloc (INITIAL_TOKEN_LENGTH)); | |
66 } | |
67 | |
68 /* Read a token from `stream' into `tokenbuffer'. | |
69 Upon return, the token is in tokenbuffer->buffer and | |
70 has a trailing '\0' instead of the original delimiter. | |
71 The function value is the length of the token not including | |
72 the final '\0'. When EOF is reached (i.e. on the call | |
73 after the last token is read), -1 is returned and tokenbuffer | |
74 isn't modified. | |
75 | |
76 This function will work properly on lines containing NUL bytes | |
77 and on files that aren't newline-terminated. */ | |
78 | |
79 long | |
1778
c30d7ad98237
(readtoken, readtokens): Protoize.
Jim Meyering <jim@meyering.net>
parents:
653
diff
changeset
|
80 readtoken (FILE *stream, |
c30d7ad98237
(readtoken, readtokens): Protoize.
Jim Meyering <jim@meyering.net>
parents:
653
diff
changeset
|
81 const char *delim, |
c30d7ad98237
(readtoken, readtokens): Protoize.
Jim Meyering <jim@meyering.net>
parents:
653
diff
changeset
|
82 int n_delim, |
c30d7ad98237
(readtoken, readtokens): Protoize.
Jim Meyering <jim@meyering.net>
parents:
653
diff
changeset
|
83 token_buffer *tokenbuffer) |
375 | 84 { |
85 char *p; | |
86 int c, i, n; | |
87 static const char *saved_delim = NULL; | |
88 static char isdelim[256]; | |
89 int same_delimiters; | |
90 | |
91 if (delim == NULL && saved_delim == NULL) | |
92 abort (); | |
93 | |
94 same_delimiters = 0; | |
95 if (delim != saved_delim && saved_delim != NULL) | |
96 { | |
97 same_delimiters = 1; | |
98 for (i = 0; i < n_delim; i++) | |
99 { | |
100 if (delim[i] != saved_delim[i]) | |
101 { | |
102 same_delimiters = 0; | |
103 break; | |
104 } | |
105 } | |
106 } | |
107 | |
108 if (!same_delimiters) | |
109 { | |
110 const char *t; | |
111 saved_delim = delim; | |
112 for (i = 0; i < sizeof (isdelim); i++) | |
113 isdelim[i] = 0; | |
114 for (t = delim; *t; t++) | |
115 isdelim[(unsigned int) *t] = 1; | |
116 } | |
117 | |
118 p = tokenbuffer->buffer; | |
119 n = tokenbuffer->size; | |
120 i = 0; | |
121 | |
122 /* FIXME: don't fool with this caching BS. Use strchr instead. */ | |
123 /* skip over any leading delimiters */ | |
124 for (c = getc (stream); c >= 0 && isdelim[c]; c = getc (stream)) | |
125 { | |
126 /* empty */ | |
127 } | |
128 | |
129 for (;;) | |
130 { | |
131 if (i >= n) | |
132 { | |
133 n = 3 * (n / 2 + 1); | |
134 p = xrealloc (p, (unsigned int) n); | |
135 } | |
136 if (c < 0) | |
137 { | |
138 if (i == 0) | |
139 return (-1); | |
140 p[i] = 0; | |
141 break; | |
142 } | |
143 if (isdelim[c]) | |
144 { | |
145 p[i] = 0; | |
146 break; | |
147 } | |
148 p[i++] = c; | |
149 c = getc (stream); | |
150 } | |
151 | |
152 tokenbuffer->buffer = p; | |
153 tokenbuffer->size = n; | |
154 return (i); | |
155 } | |
156 | |
157 /* Return a NULL-terminated array of pointers to tokens | |
158 read from `stream.' The number of tokens is returned | |
159 as the value of the function. | |
160 All storage is obtained through calls to malloc(); | |
161 | |
162 %%% Question: is it worth it to do a single | |
163 %%% realloc() of `tokens' just before returning? */ | |
164 | |
165 int | |
1778
c30d7ad98237
(readtoken, readtokens): Protoize.
Jim Meyering <jim@meyering.net>
parents:
653
diff
changeset
|
166 readtokens (FILE *stream, |
c30d7ad98237
(readtoken, readtokens): Protoize.
Jim Meyering <jim@meyering.net>
parents:
653
diff
changeset
|
167 int projected_n_tokens, |
c30d7ad98237
(readtoken, readtokens): Protoize.
Jim Meyering <jim@meyering.net>
parents:
653
diff
changeset
|
168 const char *delim, |
c30d7ad98237
(readtoken, readtokens): Protoize.
Jim Meyering <jim@meyering.net>
parents:
653
diff
changeset
|
169 int n_delim, |
c30d7ad98237
(readtoken, readtokens): Protoize.
Jim Meyering <jim@meyering.net>
parents:
653
diff
changeset
|
170 char ***tokens_out, |
c30d7ad98237
(readtoken, readtokens): Protoize.
Jim Meyering <jim@meyering.net>
parents:
653
diff
changeset
|
171 long **token_lengths) |
375 | 172 { |
173 token_buffer tb, *token = &tb; | |
174 int token_length; | |
175 char **tokens; | |
176 long *lengths; | |
177 int sz; | |
178 int n_tokens; | |
179 | |
180 n_tokens = 0; | |
181 if (projected_n_tokens > 0) | |
182 projected_n_tokens++; /* add one for trailing NULL pointer */ | |
183 else | |
184 projected_n_tokens = 64; | |
185 sz = projected_n_tokens; | |
186 tokens = (char **) xmalloc (sz * sizeof (char *)); | |
187 lengths = (long *) xmalloc (sz * sizeof (long)); | |
188 | |
189 init_tokenbuffer (token); | |
190 for (;;) | |
191 { | |
192 char *tmp; | |
193 token_length = readtoken (stream, delim, n_delim, token); | |
194 if (n_tokens >= sz) | |
195 { | |
196 sz *= 2; | |
197 tokens = (char **) xrealloc (tokens, sz * sizeof (char *)); | |
198 lengths = (long *) xrealloc (lengths, sz * sizeof (long)); | |
199 } | |
200 | |
201 if (token_length < 0) | |
202 { | |
203 /* don't increment n_tokens for NULL entry */ | |
204 tokens[n_tokens] = NULL; | |
205 lengths[n_tokens] = -1; | |
206 break; | |
207 } | |
208 tmp = (char *) xmalloc ((token_length + 1) * sizeof (char)); | |
209 lengths[n_tokens] = token_length; | |
210 tokens[n_tokens] = strncpy (tmp, token->buffer, | |
211 (unsigned) (token_length + 1)); | |
212 n_tokens++; | |
213 } | |
214 | |
215 free (token->buffer); | |
216 *tokens_out = tokens; | |
217 if (token_lengths != NULL) | |
218 *token_lengths = lengths; | |
219 return n_tokens; | |
220 } |