X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=coreutils%2Fwc.c;h=d0e5482ca500ca141f2abebd5db5ce6c06f46ada;hb=11a6f9b44f4a425b03e3a7a984e7b3e253e5f884;hp=7799015241a35646137b20018abf52ff5dd2cd43;hpb=cad5364599eb5062d59e0c397ed638ddd61a8d5d;p=oweals%2Fbusybox.git diff --git a/coreutils/wc.c b/coreutils/wc.c index 779901524..d0e5482ca 100644 --- a/coreutils/wc.c +++ b/coreutils/wc.c @@ -4,20 +4,7 @@ * * Copyright (C) 2003 Manuel Novoa III * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ /* BB_AUDIT SUSv3 _NOT_ compliant -- option -m is not currently supported. */ @@ -26,7 +13,7 @@ /* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) * * Rewritten to fix a number of problems and do some size optimizations. - * Problems in the previous busybox implementation (besides bloat) included: + * Problems in the previous busybox implementation (besides bloat) included: * 1) broken 'wc -c' optimization (read note below) * 2) broken handling of '-' args * 3) no checking of ferror on EOF returns @@ -49,20 +36,14 @@ * (adapted from example in gnu wc.c) * * echo hello > /tmp/testfile && - * (dd ibs=1k skip=1 count=0 &> /dev/null ; wc -c) < /tmp/testfile + * (dd ibs=1k skip=1 count=0 &> /dev/null; wc -c) < /tmp/testfile * * for which 'wc -c' should output '0'. */ -#include -#include -#include -#include -#include "busybox.h" +#include "libbb.h" -#ifdef CONFIG_LOCALE_SUPPORT -#include -#include +#if ENABLE_LOCALE_SUPPORT #define isspace_given_isprint(c) isspace(c) #else #undef isspace @@ -72,6 +53,14 @@ #define isspace_given_isprint(c) ((c) == ' ') #endif +#if ENABLE_FEATURE_WC_LARGE +#define COUNT_T unsigned long long +#define COUNT_FMT "llu" +#else +#define COUNT_T unsigned +#define COUNT_FMT "u" +#endif + enum { WC_LINES = 0, WC_WORDS = 1, @@ -79,65 +68,57 @@ enum { WC_LENGTH = 3 }; -/* Note: If this changes, remember to change the initialization of - * 'name' in wc_main. It needs to point to the terminating nul. */ -static const char wc_opts[] = "lwcL"; /* READ THE WARNING ABOVE! */ - -enum { - OP_INC_LINE = 1, /* OP_INC_LINE must be 1. */ - OP_SPACE = 2, - OP_NEWLINE = 4, - OP_TAB = 8, - OP_NUL = 16, -}; - -/* Note: If fmt_str changes, the offsets to 's' in the OUTPUT section - * will need to be updated. */ -static const char fmt_str[] = " %7u\0 %s\n"; -static const char total_str[] = "total"; - -int wc_main(int argc, char **argv) +int wc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int wc_main(int argc UNUSED_PARAM, char **argv) { FILE *fp; - const char *s; - unsigned int *pcounts; - unsigned int counts[4]; - unsigned int totals[4]; - unsigned int linepos; - unsigned int u; + const char *s, *arg; + const char *start_fmt = " %9"COUNT_FMT + 1; + const char *fname_fmt = " %s\n"; + COUNT_T *pcounts; + COUNT_T counts[4]; + COUNT_T totals[4]; + unsigned linepos; + unsigned u; int num_files = 0; int c; - char status = EXIT_SUCCESS; - char in_word; - char print_type; - - print_type = bb_getopt_ulflags(argc, argv, wc_opts); - + smallint status = EXIT_SUCCESS; + smallint in_word; + unsigned print_type; + + print_type = getopt32(argv, "lwcL"); + if (print_type == 0) { print_type = (1 << WC_LINES) | (1 << WC_WORDS) | (1 << WC_CHARS); } - + argv += optind; - if (!*argv) { + if (!argv[0]) { *--argv = (char *) bb_msg_standard_input; + fname_fmt = "\n"; + if (!((print_type-1) & print_type)) /* exactly one option? */ + start_fmt = "%"COUNT_FMT; } - + memset(totals, 0, sizeof(totals)); - + pcounts = counts; - - do { + + while ((arg = *argv++) != 0) { ++num_files; - if (!(fp = bb_wfopen_input(*argv))) { + fp = fopen_or_warn_stdin(arg); + if (!fp) { status = EXIT_FAILURE; continue; } - + memset(counts, 0, sizeof(counts)); linepos = 0; in_word = 0; - + do { + /* Our -w doesn't match GNU wc exactly... oh well */ + ++counts[WC_CHARS]; c = getc(fp); if (isprint(c)) { @@ -169,7 +150,7 @@ int wc_main(int argc, char **argv) } } else if (c == EOF) { if (ferror(fp)) { - bb_perror_msg("%s", *argv); + bb_simple_perror_msg(arg); status = EXIT_FAILURE; } --counts[WC_CHARS]; @@ -177,51 +158,48 @@ int wc_main(int argc, char **argv) } else { continue; } - + counts[WC_WORDS] += in_word; in_word = 0; if (c == EOF) { break; } } while (1); - + if (totals[WC_LENGTH] < counts[WC_LENGTH]) { totals[WC_LENGTH] = counts[WC_LENGTH]; } totals[WC_LENGTH] -= counts[WC_LENGTH]; - - bb_fclose_nonstdin(fp); - + + fclose_if_not_stdin(fp); + OUTPUT: - s = fmt_str + 1; /* Skip the leading space on 1st pass. */ + /* coreutils wc tries hard to print pretty columns + * (saves results for all files, find max col len etc...) + * we won't try that hard, it will bloat us too much */ + s = start_fmt; u = 0; do { if (print_type & (1 << u)) { - bb_printf(s, pcounts[u]); - s = fmt_str; /* Ok... restore the leading space. */ + printf(s, pcounts[u]); + s = " %9"COUNT_FMT; /* Ok... restore the leading space. */ } totals[u] += pcounts[u]; } while (++u < 4); - - s += 8; /* Set the format to the empty string. */ - - if (*argv != bb_msg_standard_input) { - s -= 3; /* We have a name, so do %s conversion. */ - } - bb_printf(s, *argv); - - } while (*++argv); - + printf(fname_fmt, arg); + } + /* If more than one file was processed, we want the totals. To save some * space, we set the pcounts ptr to the totals array. This has the side * effect of trashing the totals array after outputting it, but that's * irrelavent since we no longer need it. */ if (num_files > 1) { num_files = 0; /* Make sure we don't get here again. */ - *--argv = (char *) total_str; + arg = "total"; pcounts = totals; + --argv; goto OUTPUT; } - - bb_fflush_stdout_and_exit(status); + + fflush_stdout_and_exit(status); }