Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/coreutils/src/gnulib/lib/readtokens.c |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | /* readtokens.c -- Functions for reading tokens from an input stream. | - | ||||||||||||
2 | - | |||||||||||||
3 | Copyright (C) 1990-1991, 1999-2004, 2006, 2009-2018 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 3 of the License, or | - | ||||||||||||
9 | (at your option) 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, see <https://www.gnu.org/licenses/>. | - | ||||||||||||
18 | - | |||||||||||||
19 | Written by Jim Meyering. */ | - | ||||||||||||
20 | - | |||||||||||||
21 | /* This almost supersedes xreadline stuff -- using delim="\n" | - | ||||||||||||
22 | gives the same functionality, except that these functions | - | ||||||||||||
23 | would never return empty lines. */ | - | ||||||||||||
24 | - | |||||||||||||
25 | #include <config.h> | - | ||||||||||||
26 | - | |||||||||||||
27 | #include "readtokens.h" | - | ||||||||||||
28 | - | |||||||||||||
29 | #include <limits.h> | - | ||||||||||||
30 | #include <stdio.h> | - | ||||||||||||
31 | #include <stdlib.h> | - | ||||||||||||
32 | #include <string.h> | - | ||||||||||||
33 | #include <stdbool.h> | - | ||||||||||||
34 | - | |||||||||||||
35 | #include "xalloc.h" | - | ||||||||||||
36 | - | |||||||||||||
37 | #if USE_UNLOCKED_IO | - | ||||||||||||
38 | # include "unlocked-io.h" | - | ||||||||||||
39 | #endif | - | ||||||||||||
40 | - | |||||||||||||
41 | /* Initialize a tokenbuffer. */ | - | ||||||||||||
42 | - | |||||||||||||
43 | void | - | ||||||||||||
44 | init_tokenbuffer (token_buffer *tokenbuffer) | - | ||||||||||||
45 | { | - | ||||||||||||
46 | tokenbuffer->size = 0; | - | ||||||||||||
47 | tokenbuffer->buffer = NULL; | - | ||||||||||||
48 | } executed 15 times by 2 tests: end of block Executed by:
| 15 | ||||||||||||
49 | - | |||||||||||||
50 | typedef size_t word; | - | ||||||||||||
51 | enum { bits_per_word = sizeof (word) * CHAR_BIT }; | - | ||||||||||||
52 | - | |||||||||||||
53 | static bool | - | ||||||||||||
54 | get_nth_bit (size_t n, word const *bitset) | - | ||||||||||||
55 | { | - | ||||||||||||
56 | return bitset[n / bits_per_word] >> n % bits_per_word & 1; executed 3944754 times by 2 tests: return bitset[n / bits_per_word] >> n % bits_per_word & 1; Executed by:
| 3944754 | ||||||||||||
57 | } | - | ||||||||||||
58 | - | |||||||||||||
59 | static void | - | ||||||||||||
60 | set_nth_bit (size_t n, word *bitset) | - | ||||||||||||
61 | { | - | ||||||||||||
62 | size_t one = 1; | - | ||||||||||||
63 | bitset[n / bits_per_word] |= one << n % bits_per_word; | - | ||||||||||||
64 | } executed 1500336 times by 2 tests: end of block Executed by:
| 1500336 | ||||||||||||
65 | - | |||||||||||||
66 | /* Read a token from STREAM into TOKENBUFFER. | - | ||||||||||||
67 | A token is delimited by any of the N_DELIM bytes in DELIM. | - | ||||||||||||
68 | Upon return, the token is in tokenbuffer->buffer and | - | ||||||||||||
69 | has a trailing '\0' instead of any original delimiter. | - | ||||||||||||
70 | The function value is the length of the token not including | - | ||||||||||||
71 | the final '\0'. Upon EOF (i.e. on the call after the last | - | ||||||||||||
72 | token is read) or error, return -1 without modifying tokenbuffer. | - | ||||||||||||
73 | The EOF and error conditions may be distinguished in the caller | - | ||||||||||||
74 | by testing ferror (STREAM). | - | ||||||||||||
75 | - | |||||||||||||
76 | This function works properly on lines containing NUL bytes | - | ||||||||||||
77 | and on files that do not end with a delimiter. */ | - | ||||||||||||
78 | - | |||||||||||||
79 | size_t | - | ||||||||||||
80 | readtoken (FILE *stream, | - | ||||||||||||
81 | const char *delim, | - | ||||||||||||
82 | size_t n_delim, | - | ||||||||||||
83 | token_buffer *tokenbuffer) | - | ||||||||||||
84 | { | - | ||||||||||||
85 | char *p; | - | ||||||||||||
86 | int c; | - | ||||||||||||
87 | size_t i, n; | - | ||||||||||||
88 | word isdelim[(UCHAR_MAX + bits_per_word) / bits_per_word]; | - | ||||||||||||
89 | - | |||||||||||||
90 | memset (isdelim, 0, sizeof isdelim); | - | ||||||||||||
91 | for (i = 0; i < n_delim; i++)
| 500112-1500336 | ||||||||||||
92 | { | - | ||||||||||||
93 | unsigned char ch = delim[i]; | - | ||||||||||||
94 | set_nth_bit (ch, isdelim); | - | ||||||||||||
95 | } executed 1500336 times by 2 tests: end of block Executed by:
| 1500336 | ||||||||||||
96 | - | |||||||||||||
97 | /* skip over any leading delimiters */ | - | ||||||||||||
98 | for (c = getc (stream); c >= 0 && get_nth_bit (c, isdelim); c = getc (stream))
| 0-500097 | ||||||||||||
99 | { | - | ||||||||||||
100 | /* empty */ | - | ||||||||||||
101 | } never executed: end of block | 0 | ||||||||||||
102 | - | |||||||||||||
103 | p = tokenbuffer->buffer; | - | ||||||||||||
104 | n = tokenbuffer->size; | - | ||||||||||||
105 | i = 0; | - | ||||||||||||
106 | for (;;) | - | ||||||||||||
107 | { | - | ||||||||||||
108 | if (c < 0 && i == 0)
| 0-3444657 | ||||||||||||
109 | return -1; executed 15 times by 2 tests: return -1; Executed by:
| 15 | ||||||||||||
110 | - | |||||||||||||
111 | if (i == n)
| 15-3444642 | ||||||||||||
112 | p = x2nrealloc (p, &n, sizeof *p); executed 15 times by 2 tests: p = x2nrealloc (p, &n, sizeof *p); Executed by:
| 15 | ||||||||||||
113 | - | |||||||||||||
114 | if (c < 0)
| 0-3444657 | ||||||||||||
115 | { | - | ||||||||||||
116 | p[i] = 0; | - | ||||||||||||
117 | break; never executed: break; | 0 | ||||||||||||
118 | } | - | ||||||||||||
119 | if (get_nth_bit (c, isdelim))
| 500097-2944560 | ||||||||||||
120 | { | - | ||||||||||||
121 | p[i] = 0; | - | ||||||||||||
122 | break; executed 500097 times by 2 tests: break; Executed by:
| 500097 | ||||||||||||
123 | } | - | ||||||||||||
124 | p[i++] = c; | - | ||||||||||||
125 | c = getc (stream); | - | ||||||||||||
126 | } executed 2944560 times by 2 tests: end of block Executed by:
| 2944560 | ||||||||||||
127 | - | |||||||||||||
128 | tokenbuffer->buffer = p; | - | ||||||||||||
129 | tokenbuffer->size = n; | - | ||||||||||||
130 | return i; executed 500097 times by 2 tests: return i; Executed by:
| 500097 | ||||||||||||
131 | } | - | ||||||||||||
132 | - | |||||||||||||
133 | /* Build a NULL-terminated array of pointers to tokens | - | ||||||||||||
134 | read from STREAM. Return the number of tokens read. | - | ||||||||||||
135 | All storage is obtained through calls to xmalloc-like functions. | - | ||||||||||||
136 | - | |||||||||||||
137 | %%% Question: is it worth it to do a single | - | ||||||||||||
138 | %%% realloc() of 'tokens' just before returning? */ | - | ||||||||||||
139 | - | |||||||||||||
140 | size_t | - | ||||||||||||
141 | readtokens (FILE *stream, | - | ||||||||||||
142 | size_t projected_n_tokens, | - | ||||||||||||
143 | const char *delim, | - | ||||||||||||
144 | size_t n_delim, | - | ||||||||||||
145 | char ***tokens_out, | - | ||||||||||||
146 | size_t **token_lengths) | - | ||||||||||||
147 | { | - | ||||||||||||
148 | token_buffer tb, *token = &tb; | - | ||||||||||||
149 | char **tokens; | - | ||||||||||||
150 | size_t *lengths; | - | ||||||||||||
151 | size_t sz; | - | ||||||||||||
152 | size_t n_tokens; | - | ||||||||||||
153 | - | |||||||||||||
154 | if (projected_n_tokens == 0)
| 0 | ||||||||||||
155 | projected_n_tokens = 64; never executed: projected_n_tokens = 64; | 0 | ||||||||||||
156 | else | - | ||||||||||||
157 | projected_n_tokens++; /* add one for trailing NULL pointer */ never executed: projected_n_tokens++; | 0 | ||||||||||||
158 | - | |||||||||||||
159 | sz = projected_n_tokens; | - | ||||||||||||
160 | tokens = xnmalloc (sz, sizeof *tokens); | - | ||||||||||||
161 | lengths = xnmalloc (sz, sizeof *lengths); | - | ||||||||||||
162 | - | |||||||||||||
163 | n_tokens = 0; | - | ||||||||||||
164 | init_tokenbuffer (token); | - | ||||||||||||
165 | for (;;) | - | ||||||||||||
166 | { | - | ||||||||||||
167 | char *tmp; | - | ||||||||||||
168 | size_t token_length = readtoken (stream, delim, n_delim, token); | - | ||||||||||||
169 | if (n_tokens >= sz)
| 0 | ||||||||||||
170 | { | - | ||||||||||||
171 | tokens = x2nrealloc (tokens, &sz, sizeof *tokens); | - | ||||||||||||
172 | lengths = xnrealloc (lengths, sz, sizeof *lengths); | - | ||||||||||||
173 | } never executed: end of block | 0 | ||||||||||||
174 | - | |||||||||||||
175 | if (token_length == (size_t) -1)
| 0 | ||||||||||||
176 | { | - | ||||||||||||
177 | /* don't increment n_tokens for NULL entry */ | - | ||||||||||||
178 | tokens[n_tokens] = NULL; | - | ||||||||||||
179 | lengths[n_tokens] = 0; | - | ||||||||||||
180 | break; never executed: break; | 0 | ||||||||||||
181 | } | - | ||||||||||||
182 | tmp = xnmalloc (token_length + 1, sizeof *tmp); | - | ||||||||||||
183 | lengths[n_tokens] = token_length; | - | ||||||||||||
184 | tokens[n_tokens] = memcpy (tmp, token->buffer, token_length + 1); | - | ||||||||||||
185 | n_tokens++; | - | ||||||||||||
186 | } never executed: end of block | 0 | ||||||||||||
187 | - | |||||||||||||
188 | free (token->buffer); | - | ||||||||||||
189 | *tokens_out = tokens; | - | ||||||||||||
190 | if (token_lengths != NULL)
| 0 | ||||||||||||
191 | *token_lengths = lengths; never executed: *token_lengths = lengths; | 0 | ||||||||||||
192 | else | - | ||||||||||||
193 | free (lengths); never executed: free (lengths); | 0 | ||||||||||||
194 | return n_tokens; never executed: return n_tokens; | 0 | ||||||||||||
195 | } | - | ||||||||||||
Source code | Switch to Preprocessed file |