(root)/
coreutils-9.4/
lib/
readtokens0.c
       1  /* readtokens0.c -- Read NUL-separated tokens from an input stream.
       2  
       3     Copyright (C) 2004, 2006, 2009-2023 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 <https://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  
      29  void
      30  readtokens0_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  
      40  void
      41  readtokens0_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.  */
      50  static void
      51  save_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.  */
      65  bool
      66  readtokens0 (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  }