1/* Iterate over arguments from argv or --files0-from=FILE 2 Copyright (C) 2008-2010 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 3 of the License, or 7 (at your option) 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, see <http://www.gnu.org/licenses/>. */ 16 17/* Written by Jim Meyering. */ 18 19#include <config.h> 20#include "argv-iter.h" 21 22#include <stdlib.h> 23#include <string.h> 24 25struct argv_iterator 26{ 27 /* Test FP to determine whether in read-mode or argv-mode. */ 28 /* file-mode: fp records position */ 29 FILE *fp; 30 size_t item_idx; 31 char *tok; 32 size_t buf_len; 33 34 /* argv-mode: record just argv and current pointer */ 35 char **arg_list; 36 char **p; 37}; 38 39struct argv_iterator * 40argv_iter_init_argv (char **argv) 41{ 42 struct argv_iterator *ai = malloc (sizeof *ai); 43 if (!ai) 44 return NULL; 45 ai->fp = NULL; 46 ai->arg_list = argv; 47 ai->p = argv; 48 return ai; 49} 50 51/* Initialize to read from the stream, FP. 52 The input is expected to contain a list of NUL-delimited tokens. */ 53struct argv_iterator * 54argv_iter_init_stream (FILE *fp) 55{ 56 struct argv_iterator *ai = malloc (sizeof *ai); 57 if (!ai) 58 return NULL; 59 ai->fp = fp; 60 ai->tok = NULL; 61 ai->buf_len = 0; 62 63 ai->item_idx = 0; 64 ai->arg_list = NULL; 65 return ai; 66} 67 68char * 69argv_iter (struct argv_iterator *ai, enum argv_iter_err *err) 70{ 71 if (ai->fp) 72 { 73 ssize_t len = getdelim (&ai->tok, &ai->buf_len, '\0', ai->fp); 74 if (len < 0) 75 { 76 *err = feof (ai->fp) ? AI_ERR_EOF : AI_ERR_READ; 77 return NULL; 78 } 79 80 *err = AI_ERR_OK; 81 ai->item_idx++; 82 return ai->tok; 83 } 84 else 85 { 86 if (*(ai->p) == NULL) 87 { 88 *err = AI_ERR_EOF; 89 return NULL; 90 } 91 else 92 { 93 *err = AI_ERR_OK; 94 return *(ai->p++); 95 } 96 } 97} 98 99size_t 100argv_iter_n_args (struct argv_iterator const *ai) 101{ 102 return ai->fp ? ai->item_idx : ai->p - ai->arg_list; 103} 104 105void 106argv_iter_free (struct argv_iterator *ai) 107{ 108 if (ai->fp) 109 free (ai->tok); 110 free (ai); 111} 112