diff options
author | Pedro J. Ruiz Lopez <holzplatten@es.gnu.org> | 2008-10-23 20:08:44 +0200 |
---|---|---|
committer | Jim Meyering <meyering@redhat.com> | 2009-07-04 18:47:49 +0200 |
commit | 2da7dc21e77a43d43696abc86700dda9259cf091 (patch) | |
tree | 713e78df15ea92839eb48107b02710127c1786be /src | |
parent | ba3da6fe033c38ffdac4fe9b60b617f26a687aaf (diff) | |
download | idutils-2da7dc21e77a43d43696abc86700dda9259cf091.tar.gz idutils-2da7dc21e77a43d43696abc86700dda9259cf091.tar.bz2 idutils-2da7dc21e77a43d43696abc86700dda9259cf091.zip |
mkid, xtokid: accept a new option --files0-from=FILE
* bootstrap.conf (gnulib_modules): Add quote and readtokens0.
* doc/idutils.texi: Document the option.
* src/mkid.c (usage, FILES0_FROM_OPTION, long_options, help_me)
(main): Implement.
* src/xtokid.c (usage, FILES0_FROM_OPTION, long_options, help_me)
(main): Likewise.
Diffstat (limited to 'src')
-rw-r--r-- | src/mkid.c | 130 | ||||
-rw-r--r-- | src/xtokid.c | 124 |
2 files changed, 216 insertions, 38 deletions
@@ -24,23 +24,27 @@ #include <getopt.h> #include <stddef.h> #include <unistd.h> -#include <pathmax.h> #include <string.h> -#include <dirname.h> -#include <alloca.h> -#include <limits.h> -#include <inttostr.h> -#include <xalloc.h> -#include <error.h> #include <sys/stat.h> +#include <limits.h> +#include "alloca.h" #include "closeout.h" +#include "dirname.h" +#include "error.h" +#include "inttostr.h" +#include "pathmax.h" +#include "progname.h" +#include "quote.h" +#include "quotearg.h" +#include "readtokens0.h" +#include "xalloc.h" + #include "xnls.h" #include "idfile.h" #include "hash.h" #include "scanners.h" #include "iduglobal.h" -#include "progname.h" struct summary { @@ -125,9 +129,16 @@ usage (void) { fprintf (stderr, _("Try `%s --help' for more information.\n"), program_name); - exit (1); + exit (EXIT_FAILURE); } +/* For long options that have no equivalent short option, use a + non-character as a pseudo short option, starting with CHAR_MAX + 1. */ +enum +{ + FILES0_FROM_OPTION = CHAR_MAX +1, +}; + static struct option const long_options[] = { { "file", required_argument, 0, 'f' }, @@ -142,6 +153,7 @@ static struct option const long_options[] = { "statistics", no_argument, 0, 's' }, { "help", no_argument, &show_help, 1 }, { "version", no_argument, &show_version, 1 }, + { "files0-from", required_argument, NULL, FILES0_FROM_OPTION }, {NULL, 0, NULL, 0} }; @@ -165,7 +177,10 @@ Build an identifier database.\n\ -v, --verbose report per file statistics\n\ -s, --statistics report statistics at end of run\n\ \n\ - --help display this help and exit\n\ + --files0-from=F tokenize only the files specified by\n\ + NUL-terminated names in file F\n\ +\n\ + --help display this help and exit\n\ --version output version information and exit\n\ \n\ FILE may be a file name, or a directory name to recursively search.\n\ @@ -176,7 +191,7 @@ The following arguments apply to the language-specific scanners:\n\ ")); language_help_me (); printf (_("\nReport bugs to " PACKAGE_BUGREPORT "\n\n")); - exit (0); + exit (EXIT_SUCCESS); } static void *heap_initial; @@ -195,6 +210,13 @@ static void *get_process_heap(void) int main (int argc, char **argv) { + bool ok; + int i; + int nfiles; + char **files; + char *files_from = NULL; + struct Tokens tok; + set_program_name (argv[0]); heap_initial = get_process_heap(); idh.idh_file_name = DEFAULT_ID_FILE_NAME; @@ -252,6 +274,10 @@ main (int argc, char **argv) prune_file_names (optarg, cw_dlink); break; + case FILES0_FROM_OPTION: + files_from = optarg; + break; + case 'V': walker_verbose_flag = 1; case 'v': @@ -274,16 +300,42 @@ main (int argc, char **argv) if (show_help) help_me (); - argc -= optind; - argv += optind; + nfiles = argc - optind; + files = argv + optind; + + if (files_from) + { + /* When using --files0-from=F, you may not specify any files + on the command-line. */ + if (nfiles != 0) + { + error (0, 0, _("extra operand %s"), quote (argv[optind])); + fprintf (stderr, "%s\n", + _("File operands cannot be combined with --files0-from.")); + usage(); + } + + if (! (strequ (files_from, "-") || freopen (files_from, "r", stdin))) + error (EXIT_FAILURE, errno, _("cannot open %s for reading"), + quote (files_from)); + + readtokens0_init (&tok); + + if (! readtokens0 (stdin, &tok) || fclose (stdin) != 0) + error (EXIT_FAILURE, 0, _("cannot read file names from %s"), + quote (files_from)); + + nfiles = tok.n_tok; + files = tok.tok; + } /* If no file or directory options exist, walk the current directory. */ - if (argc == 0) + else if (nfiles == 0) { static char dot[] = "."; static char *dotp = dot; - argc = 1; - argv = &dotp; + nfiles = 1; + files = &dotp; } language_getopt (); @@ -293,11 +345,47 @@ main (int argc, char **argv) parse_language_map (lang_map_file_name); /* Walk the file and directory names given on the command line. */ - while (argc--) + ok = true; + for (i=0; i < nfiles; i++) { - struct file_link *flink = parse_file_name (*argv++, cw_dlink); - if (flink) - walk_flink (flink, 0); + if (*files) + { + struct file_link *flink; + + if (files_from && strequ(files_from, "-") && strequ(files[i], "-")) + { + ok = false; + /* Give a better diagnostic in an unusual case: + printf - | wc --files0-from=- */ + error (0, 0, _("when reading file names from stdin, " + "no file name of %s allowed"), + quote ("-")); + continue; + } + + /* Diagnose a zero-length file name. When it's one + among many, knowing the record number may help. */ + if (files[i][0] == '\0') + { + ok = false; + if (files_from) + { + /* Using the standard `filename:line-number:' prefix here is + not totally appropriate, since NUL is the separator, not NL, + but it might be better than nothing. */ + unsigned long int file_number = i + 1; + error (0, 0, "%s:%lu: %s", quotearg_colon (files_from), + file_number, _("invalid zero-length file name")); + } + else + error (0, 0, "%s", _("invalid zero-length file name")); + continue; + } + + flink = parse_file_name (files[i], cw_dlink); + if (flink) + walk_flink (flink, 0); + } } heap_after_walk = get_process_heap(); @@ -337,7 +425,7 @@ main (int argc, char **argv) else error (0, 0, _("nothing to do")); - exit (0); + exit (ok ? EXIT_SUCCESS : EXIT_FAILURE); } /* Return the integer ceiling of the base-8 logarithm of N. */ diff --git a/src/xtokid.c b/src/xtokid.c index 8f77980..1c86e05 100644 --- a/src/xtokid.c +++ b/src/xtokid.c @@ -22,16 +22,20 @@ #include <string.h> #include <stdlib.h> #include <errno.h> -#include <xalloc.h> -#include <pathmax.h> -#include <error.h> #include "closeout.h" +#include "error.h" +#include "pathmax.h" +#include "progname.h" +#include "quote.h" +#include "quotearg.h" +#include "readtokens0.h" +#include "xalloc.h" + #include "xnls.h" #include "scanners.h" #include "idfile.h" #include "iduglobal.h" -#include "progname.h" static void scan_files (struct idhead *idhp); static void scan_member_file (struct member_file const *member); @@ -48,9 +52,16 @@ usage (void) { fprintf (stderr, _("Try `%s --help' for more information.\n"), program_name); - exit (1); + exit (EXIT_FAILURE); } +/* For long options that have no equivalent short option, use a + non-character as a pseudo short option, starting with CHAR_MAX + 1. */ +enum +{ + FILES0_FROM_OPTION = CHAR_MAX +1, +}; + static struct option const long_options[] = { { "include", required_argument, 0, 'i' }, @@ -61,6 +72,7 @@ static struct option const long_options[] = { "prune", required_argument, 0, 'p' }, { "help", no_argument, &show_help, 1 }, { "version", no_argument, &show_version, 1 }, + { "files0-from", required_argument, NULL, FILES0_FROM_OPTION }, {NULL, 0, NULL, 0} }; @@ -79,7 +91,11 @@ Print all tokens found in a source file.\n\ -m, --lang-map=MAPFILE use MAPFILE to map file names onto source language\n\ -d, --default-lang=LANG make LANG the default source language\n\ -p, --prune=NAMES exclude the named files and/or directories\n\ - --help display this help and exit\n\ +\n\ + --files0-from=F tokenize only the files specified by\n\ + NUL-terminated names in file F\n\ +\n\ + --help display this help and exit\n \ --version output version information and exit\n\ \n\ The following arguments apply to the language-specific scanners:\n\ @@ -92,6 +108,13 @@ The following arguments apply to the language-specific scanners:\n\ int main (int argc, char **argv) { + bool ok; + int i; + int nfiles; + char **files; + char *files_from = NULL; + struct Tokens tok; + set_program_name (argv[0]); #if ENABLE_NLS @@ -142,6 +165,10 @@ main (int argc, char **argv) prune_file_names (optarg, cw_dlink); break; + case FILES0_FROM_OPTION: + files_from = optarg; + break; + default: usage (); } @@ -150,20 +177,47 @@ main (int argc, char **argv) if (show_version) { printf ("%s - %s\n", program_name, PACKAGE_VERSION); - exit (0); + exit (EXIT_SUCCESS); } if (show_help) help_me (); - argc -= optind; - argv += optind; - if (argc == 0) + nfiles = argc - optind; + files = argv + optind; + + if (files_from) { + /* When using --files0-from=F, you may not specify any files + on the command-line. */ + if (nfiles != 0) + { + error (0, 0, _("extra operand %s"), quote (argv[optind])); + fprintf (stderr, "%s\n", + _("File operands cannot be combined with --files0-from.")); + usage(); + } + + if (! (strequ (files_from, "-") || freopen (files_from, "r", stdin))) + error (EXIT_FAILURE, errno, _("cannot open %s for reading"), + quote (files_from)); + + readtokens0_init (&tok); + + if (! readtokens0 (stdin, &tok) || fclose (stdin) != 0) + error (EXIT_FAILURE, 0, _("cannot read file names from %s"), + quote (files_from)); + + nfiles = tok.n_tok; + files = tok.tok; + } + /* If no file or directory options exist, walk the current directory. */ + else if (nfiles == 0) + { static char dot[] = "."; static char *dotp = dot; - argc = 1; - argv = &dotp; + nfiles = 1; + files = &dotp; } language_getopt (); @@ -171,17 +225,53 @@ main (int argc, char **argv) cw_dlink = init_walker (&idh); parse_language_map (lang_map_file_name); - while (argc--) + ok = true; + for (i=0; i < nfiles; i++) { - struct file_link *flink = parse_file_name (*argv++, cw_dlink); - if (flink) - walk_flink (flink, 0); + if (*files) + { + struct file_link *flink; + + if (files_from && strequ(files_from, "-") && strequ(files[i], "-")) + { + ok = false; + /* Give a better diagnostic in an unusual case: + printf - | wc --files0-from=- */ + error (0, 0, _("when reading file names from stdin, " + "no file name of %s allowed"), + quote ("-")); + continue; + } + + /* Diagnose a zero-length file name. When it's one + among many, knowing the record number may help. */ + if (files[i][0] == '\0') + { + ok = false; + if (files_from) + { + /* Using the standard `filename:line-number:' prefix here is + not totally appropriate, since NUL is the separator, not NL, + but it might be better than nothing. */ + unsigned long int file_number = i + 1; + error (0, 0, "%s:%lu: %s", quotearg_colon (files_from), + file_number, _("invalid zero-length file name")); + } + else + error (0, 0, "%s", _("invalid zero-length file name")); + continue; + } + + flink = parse_file_name (files[i], cw_dlink); + if (flink) + walk_flink (flink, 0); + } } mark_member_file_links (&idh); obstack_init (&tokens_obstack); scan_files (&idh); - return 0; + exit (ok ? EXIT_SUCCESS : EXIT_FAILURE); } static void |