lazysphere/command/wc.c

162 lines
3.4 KiB
C
Raw Normal View History

2023-05-06 04:39:44 +00:00
#include "command.h"
#include "lslib.h"
2023-05-01 04:31:13 +00:00
#include <ctype.h>
2023-05-06 04:39:44 +00:00
#include <stdlib.h>
2023-05-01 04:31:13 +00:00
2023-05-01 22:43:32 +00:00
static struct {
2023-05-01 04:31:13 +00:00
bool newlines;
bool words;
bool characters;
bool bytes;
bool longest_line;
2023-05-01 22:43:32 +00:00
bool has_flags;
} flags;
2023-05-01 04:31:13 +00:00
static int lines = 0;
static int words = 0;
static int chars = 0;
static int bytes = 0;
static int logst = 0;
2023-05-01 22:43:32 +00:00
static void list(int l, int w, int c, int b, int lg) {
if (flags.newlines) {
2023-05-01 04:31:13 +00:00
printf("\t%d", l);
}
2023-05-01 22:43:32 +00:00
if (flags.words) {
2023-05-01 04:31:13 +00:00
printf("\t%d", w);
}
2023-05-01 22:43:32 +00:00
if (flags.characters) {
2023-05-01 04:31:13 +00:00
printf("\t%d", c);
}
2023-05-01 22:43:32 +00:00
if (flags.bytes) {
2023-05-01 04:31:13 +00:00
printf("\t%d", b);
}
2023-05-01 22:43:32 +00:00
if (flags.longest_line) {
2023-05-01 04:31:13 +00:00
printf("\t%d", lg);
}
}
#define BS 1024
static bool is_delimiter(char c) {
return c == ' ' || c == '\t' || c == '\n';
}
2023-05-01 22:43:32 +00:00
static void run_wc(FILE* file) {
2023-05-01 04:31:13 +00:00
int l = 0, w = 0, c = 0, b = 0, lg = 0;
bool in_word = false;
int current_length = 0;
int read;
char buf[BS];
while ((read = fread(buf, 1, 1024, file)) > 0) {
2023-05-04 20:10:37 +00:00
int i;
for (i = 0; i < read; i++) {
2023-05-01 04:31:13 +00:00
char ch = buf[i];
b++;
if (ch == '\n') {
l++;
lg = lg > current_length ? lg : current_length;
current_length = 0;
} else {
current_length++;
}
if (isprint(ch) || is_delimiter(ch)) c++;
if (in_word && is_delimiter(ch)) {
in_word = false;
w++;
} else if (!in_word && !is_delimiter(ch) && isprint(ch)) {
in_word = true;
}
}
}
if (in_word) w++;
lg = lg > current_length ? lg : current_length;
2023-05-01 22:43:32 +00:00
list(l, w, c, b, lg);
2023-05-01 04:31:13 +00:00
lines += l;
words += w;
chars += c;
bytes += b;
logst += lg;
if (file != stdin)
fclose(file);
}
2023-05-01 22:43:32 +00:00
static void help(void) {
2023-05-01 04:31:13 +00:00
printf("Usage: wc [-cmlwL] [FILE]...\n\n");
printf("Count lines, words, and bytes for FILEs (or stdin)\n\n");
printf("\t-c Count bytes\n");
printf("\t-m Count characters\n");
printf("\t-l Count newlines\n");
printf("\t-w Count words\n");
printf("\t-L Print longest line length\n");
exit(EXIT_SUCCESS);
}
2023-05-01 22:43:32 +00:00
static int short_arg(char c, char* next) {
UNUSED(next);
switch (c) {
case 'c':
flags.bytes = true;
break;
case 'm':
flags.characters = true;
break;
case 'l':
flags.newlines = true;
break;
case 'w':
flags.words = true;
break;
case 'L':
flags.longest_line = true;
break;
default:
2023-05-03 16:17:56 +00:00
return ARG_INVALID;
2023-05-01 22:43:32 +00:00
}
flags.has_flags = true;
return ARG_UNUSED;
}
2023-05-01 04:31:13 +00:00
COMMAND(wc) {
2023-05-04 20:10:37 +00:00
int start, i;
2023-05-01 04:31:13 +00:00
flags.newlines = false;
flags.words = false;
flags.characters = false;
flags.bytes = false;
flags.longest_line = false;
2023-05-01 22:43:32 +00:00
flags.has_flags = false;
2023-05-01 04:31:13 +00:00
2023-05-04 20:10:37 +00:00
start = parse_args(argc, argv, help, short_arg, NULL);
2023-05-01 22:43:32 +00:00
if (!flags.has_flags) {
2023-05-01 04:31:13 +00:00
flags.newlines = true;
flags.words = true;
flags.characters = true;
}
if (argc - start < 1) {
2023-05-01 22:43:32 +00:00
run_wc(stdin);
2023-05-01 04:31:13 +00:00
printf("\n");
return EXIT_SUCCESS;
}
2023-05-04 20:10:37 +00:00
for (i = start; i < argc; i++) {
2023-05-01 04:31:13 +00:00
FILE* file = get_file(argv[i], "r");
2023-05-01 22:43:32 +00:00
run_wc(file);
2023-05-01 04:31:13 +00:00
printf("\t%s\n", argv[i]);
}
if (argc - start > 1) {
2023-05-01 22:43:32 +00:00
list(lines, words, chars, bytes, logst);
2023-05-01 04:31:13 +00:00
printf("\ttotal\n");
}
return EXIT_SUCCESS;
}