| /* readtokens0.c -- Read NUL-separated tokens from an input stream. | |
| Copyright (C) 2004, 2006, 2009-2026 Free Software Foundation, Inc. | |
| This program is free software: you can redistribute it and/or modify | |
| it under the terms of the GNU General Public License as published by | |
| the Free Software Foundation, either version 3 of the License, or | |
| (at your option) any later version. | |
| This program is distributed in the hope that it will be useful, | |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| GNU General Public License for more details. | |
| You should have received a copy of the GNU General Public License | |
| along with this program. If not, see <https://www.gnu.org/licenses/>. | |
| Written by Jim Meyering. */ | |
| #include <config.h> | |
| #include <stdlib.h> | |
| #include "readtokens0.h" | |
| #define obstack_chunk_alloc malloc | |
| #define obstack_chunk_free free | |
| void | |
| readtokens0_init (struct Tokens *t) | |
| { | |
| t->n_tok = 0; | |
| t->tok = NULL; | |
| t->tok_len = NULL; | |
| obstack_init (&t->o_data); | |
| obstack_init (&t->o_tok); | |
| obstack_init (&t->o_tok_len); | |
| } | |
| void | |
| readtokens0_free (struct Tokens *t) | |
| { | |
| obstack_free (&t->o_data, NULL); | |
| obstack_free (&t->o_tok, NULL); | |
| obstack_free (&t->o_tok_len, NULL); | |
| } | |
| /* Finalize (in the obstack_finish sense) the current token | |
| and record its pointer and length. */ | |
| static void | |
| save_token (struct Tokens *t) | |
| { | |
| /* Don't count the trailing NUL byte in the length. */ | |
| size_t len = obstack_object_size (&t->o_data) - 1; | |
| char const *s = obstack_finish (&t->o_data); | |
| obstack_ptr_grow (&t->o_tok, s); | |
| obstack_grow (&t->o_tok_len, &len, sizeof len); | |
| t->n_tok++; | |
| } | |
| /* Read NUL-separated tokens from stream IN into T until EOF or error. | |
| The final NUL is optional. Always append a NULL pointer to the | |
| resulting list of token pointers, but that pointer isn't counted | |
| via t->n_tok. Return true if successful. */ | |
| bool | |
| readtokens0 (FILE *in, struct Tokens *t) | |
| { | |
| while (1) | |
| { | |
| int c = fgetc (in); | |
| if (c == EOF) | |
| { | |
| size_t len = obstack_object_size (&t->o_data); | |
| /* If the current object has nonzero length, then there | |
| was no NUL byte at EOF -- or maybe there was an error, | |
| in which case, we need to append a NUL byte to our buffer. */ | |
| if (len) | |
| { | |
| obstack_1grow (&t->o_data, '\0'); | |
| save_token (t); | |
| } | |
| break; | |
| } | |
| obstack_1grow (&t->o_data, c); | |
| if (c == '\0') | |
| save_token (t); | |
| } | |
| /* Add a NULL pointer at the end, in case the caller (like du) | |
| requires an argv-style array of strings. */ | |
| obstack_ptr_grow (&t->o_tok, NULL); | |
| t->tok = obstack_finish (&t->o_tok); | |
| t->tok_len = obstack_finish (&t->o_tok_len); | |
| return ! ferror (in); | |
| } |