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