*** empty log message ***
[gnulib.git] / lib / readtokens0.c
1 /* readtokens0.c -- Read NUL-separated tokens from an input stream.
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    Written by Jim Meyering. */
19
20 #include <config.h>
21 #include <stdlib.h>
22
23 #include "readtokens0.h"
24
25 #define obstack_chunk_alloc malloc
26 #define obstack_chunk_free free
27
28 void
29 readtokens0_init (struct Tokens *t)
30 {
31   t->n_tok = 0;
32   t->tok = NULL;
33   t->tok_len = NULL;
34   obstack_init (&t->o_data);
35   obstack_init (&t->o_tok);
36   obstack_init (&t->o_tok_len);
37 }
38
39 void
40 readtokens0_free (struct Tokens *t)
41 {
42   obstack_free (&t->o_data, NULL);
43   obstack_free (&t->o_tok, NULL);
44   obstack_free (&t->o_tok_len, NULL);
45 }
46
47 /* Finalize (in the obstack_finish sense) the current token
48    and record its pointer and length.  */
49 static void
50 save_token (struct Tokens *t)
51 {
52   /* Don't count the trailing NUL byte in the length.  */
53   size_t len = obstack_object_size (&t->o_data) - 1;
54   char const *s = obstack_finish (&t->o_data);
55   obstack_ptr_grow (&t->o_tok, s);
56   obstack_grow (&t->o_tok_len, &len, sizeof len);
57   t->n_tok++;
58 }
59
60 /* Read NUL-separated tokens from stream IN into T until EOF or error.
61    The final NUL is optional.  Always append a NULL pointer to the
62    resulting list of token pointers, but that pointer isn't counted
63    via t->n_tok.  Return true if successful.  */
64 bool
65 readtokens0 (FILE *in, struct Tokens *t)
66 {
67
68   while (1)
69     {
70       int c = fgetc (in);
71       if (c == EOF)
72         {
73           size_t len = obstack_object_size (&t->o_data);
74           /* If the current object has nonzero length, then there
75              was no NUL byte at EOF -- or maybe there was an error,
76              in which case, we need to append a NUL byte to our buffer.  */
77           if (len)
78             {
79               obstack_1grow (&t->o_data, '\0');
80               save_token (t);
81             }
82
83           break;
84         }
85
86       obstack_1grow (&t->o_data, c);
87       if (c == '\0')
88         save_token (t);
89     }
90
91   /* Add a NULL pointer at the end, in case the caller (like du)
92      requires an argv-style array of strings.  */
93   obstack_ptr_grow (&t->o_tok, NULL);
94
95   t->tok = obstack_finish (&t->o_tok);
96   t->tok_len = obstack_finish (&t->o_tok_len);
97   return ! ferror (in);
98 }