HTMLify
wc
Views: 86 | Author: abh
/* wc */
#define POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <malloc.h>
#include <ctype.h>
#include <unistd.h>
struct counting {
int bytes, words, lines, chars;
char *filename;
};
struct args {
bool
all,
bytes,
lines,
chars,
words
;
} args = {
true, false, false, false
};
int digit_count(int num) {
int count = 0;
if (!num)
return 1;
while (num != 0) {
count++;
num /= 10;
}
return count;
}
struct counting count_file(FILE *file, char *filename) {
struct counting counting = { 0, 0, 0, 0, filename};
int byte;
bool last_space = true;
while ((byte = getc(file)) != EOF) {
counting.bytes++;
if (byte == 10)
counting.lines++;
if (isspace((unsigned char)byte)) {
last_space = true;
} else {
if (last_space)
counting.words++;
last_space = false;
}
if ((byte & 0xC0) != 0x80)
counting.chars++;
}
return counting;
}
int get_span(struct counting counting) {
int span = 1,
dc_lines = digit_count(counting.lines),
dc_words = digit_count(counting.words),
dc_bytes = digit_count(counting.bytes),
dc_chars = digit_count(counting.chars)
;
if (args.all) {
if (dc_lines > span)
span = dc_lines;
if (dc_words > span)
span = dc_words;
if (dc_bytes > span)
span = dc_bytes;
return span;
}
if (args.lines + args.words + args.bytes + args.chars == 1)
return 0;
if (args.lines)
if (dc_lines > span)
span = dc_lines;
if (args.words)
if (dc_words > span)
span = dc_words;
if (args.bytes)
if (dc_bytes > span)
span = dc_bytes;
if (args.chars)
if (dc_chars > span)
span = dc_chars;
return span;
}
void print_counting(struct counting counting, int span) {
if (!span)
span = get_span(counting);
if (args.all) {
printf(
"%*d %*d %*d %s\n",
span, counting.lines,
span, counting.words,
span, counting.bytes,
counting.filename
);
return;
}
if (args.lines)
printf("%*d ", span, counting.lines);
if (args.words)
printf("%*d ", span, counting.words);
if (args.bytes)
printf("%*d ", span, counting.bytes);
if (args.chars)
printf("%*d ", span, counting.chars);
printf("%s\n", counting.filename);
}
int main(int argc, char *argv[]) {
struct counting count, *counts, tcount = { 0, 0, 0, 0, "total" };
int opt, i, count_count = 0, span = 0, return_code = 0;
bool has_stdin = false;
while((opt = getopt(argc, argv, "cmlw")) != -1) {
switch (opt) {
case 'c': {
args.all = false;
args.bytes = true;
args.chars = false;
break;
}
case 'l': {
args.all = false;
args.lines = true;
break;
}
case 'm': {
args.all = false;
args.chars = true;
args.bytes = false;
break;
}
case 'w': {
args.all = false;
args.words = true;
break;
}
default: {
fprintf(stderr, "Unknown option '-%c'\n", opt);
return_code = 1;
}
}
}
argc -= optind;
argv += optind;
FILE *file;
if (argc == 0) {
struct counting count = count_file(stdin, "");
print_counting(count, 7);
return return_code;
}
for (i=0; i<argc; i++) {
if (!strcmp(argv[i], "-")) {
file = stdin;
has_stdin = true;
} else {
file = fopen(argv[i], "r");
}
if (file == NULL) {
fprintf(stderr, "wc: %s: No such file or directory\n", argv[i]);
return_code = 1;
continue;
}
count = count_file(file, argv[i]);
tcount.bytes += count.bytes;
tcount.chars += count.chars;
tcount.words += count.words;
tcount.lines += count.lines;
if (get_span(count) > span)
span = get_span(count);
counts = realloc(counts, (count_count+1)*sizeof(struct counting));
counts[count_count] = count;
count_count++;
}
if (argc > 1)
if (get_span(tcount) > span)
span = get_span(tcount);
if (has_stdin)
span = 7;
for (i=0; i<count_count; i++) {
print_counting(counts[i], span);
}
if (argc>1)
print_counting(tcount, span);
return return_code;
}