123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- /* vim: tabstop=4 shiftwidth=4 noexpandtab
- * This file is part of ToaruOS and is released under the terms
- * of the NCSA / University of Illinois License - see LICENSE.md
- * Copyright (C) 2018 K. Lange
- *
- * wc - count bytes, characters, words, lines...
- */
- #include <stdio.h>
- #include <string.h>
- #include <unistd.h>
- #include <getopt.h>
- #include <errno.h>
- #include <toaru/decodeutf8.h>
- int main(int argc, char * argv[]) {
- int show_lines = 0;
- int show_words = 0;
- int show_chars = 0;
- int show_bytes = 0;
- int opt;
- while ((opt = getopt(argc,argv,"cmlw")) != -1) {
- switch (opt) {
- case 'c':
- show_bytes = 1;
- break;
- case 'm':
- show_chars = 1;
- break;
- case 'l':
- show_lines = 1;
- break;
- case 'w':
- show_words = 1;
- break;
- }
- }
- int retval = 0;
- int total_lines = 0;
- int total_chars = 0;
- int total_words = 0;
- int just_stdin = 0;
- if (optind == argc) {
- argv[optind] = "";
- argc++;
- just_stdin = 1;
- }
- for (int i = optind; i < argc; ++i) {
- if (!*argv[i] && !just_stdin) {
- fprintf(stderr, "%s: invalid zero-length file name\n", argv[0]);
- retval = 1;
- continue;
- }
- FILE * f = (!strcmp(argv[i], "-") || just_stdin) ? stdin : fopen(argv[i], "r");
- if (!f) {
- fprintf(stderr, "%s: %s: %s\n", argv[0], argv[i], strerror(errno));
- retval = 1;
- continue;
- }
- int lines = 0;
- int chars = 0;
- int words = 0;
- int ch;
- uint32_t state, c;
- int last_was_whitespace = 0;
- while (!feof(f)) {
- ch = getc(f);
- if (ch < 0) break;
- if (show_chars) {
- if (!decode(&state, &c, ch)) {
- } else if (state == UTF8_REJECT) {
- state = 0;
- }
- } else {
- c = ch;
- }
- chars++;
- if (c == '\n') {
- last_was_whitespace = 1;
- lines++;
- words++;
- } else if (c == ' ') {
- if (last_was_whitespace) continue;
- last_was_whitespace = 1;
- words++;
- } else {
- last_was_whitespace = 0;
- }
- }
- if (!last_was_whitespace && chars > 0) words++;
- if (!show_words && !show_chars && !show_bytes && !show_lines) {
- fprintf(stdout, "%d %d %d %s\n", lines, words, chars, argv[i]);
- } else {
- if (show_lines) fprintf(stdout, "%d ", lines);
- if (show_words) fprintf(stdout, "%d ", words);
- if (show_bytes|show_chars) fprintf(stdout, "%d ", chars);
- fprintf(stdout, "%s\n", argv[i]);
- }
- total_lines += lines;
- total_words += words;
- total_chars += chars;
- if (f != stdin) fclose(f);
- if (just_stdin) return 0;
- }
- if (optind + 1 < argc) {
- if (!show_words && !show_chars && !show_bytes && !show_lines) {
- fprintf(stdout, "%d %d %d %s\n", total_lines, total_words, total_chars, "total");
- } else {
- if (show_lines) fprintf(stdout, "%d ", total_lines);
- if (show_words) fprintf(stdout, "%d ", total_words);
- if (show_bytes|show_chars) fprintf(stdout, "%d ", total_chars);
- fprintf(stdout, "%s\n", "total");
- }
- }
- return retval;
- }
|