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