Changeset View
Changeset View
Standalone View
Standalone View
usr.bin/wc/wc.c
Show First 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | |||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <wchar.h> | #include <wchar.h> | ||||
#include <wctype.h> | #include <wctype.h> | ||||
#include <libxo/xo.h> | #include <libxo/xo.h> | ||||
#include "countnl.h" | |||||
static uintmax_t tlinect, twordct, tcharct, tlongline; | static uintmax_t tlinect, twordct, tcharct, tlongline; | ||||
static int doline, doword, dochar, domulti, dolongline; | static int doline, doword, dochar, domulti, dolongline; | ||||
static volatile sig_atomic_t siginfo; | static volatile sig_atomic_t siginfo; | ||||
static xo_handle_t *stderr_handle; | static xo_handle_t *stderr_handle; | ||||
static void show_cnt(const char *file, uintmax_t linect, uintmax_t wordct, | static void show_cnt(const char *file, uintmax_t linect, uintmax_t wordct, | ||||
uintmax_t charct, uintmax_t llct); | uintmax_t charct, uintmax_t llct); | ||||
static int cnt(const char *); | static int cnt(const char *); | ||||
▲ Show 20 Lines • Show All 129 Lines • ▼ Show 20 Lines | cnt(const char *file) | ||||
u_char *p; | u_char *p; | ||||
u_char buf[MAXBSIZE]; | u_char buf[MAXBSIZE]; | ||||
wchar_t wch; | wchar_t wch; | ||||
mbstate_t mbs; | mbstate_t mbs; | ||||
linect = wordct = charct = llct = tmpll = 0; | linect = wordct = charct = llct = tmpll = 0; | ||||
if (file == NULL) | if (file == NULL) | ||||
fd = STDIN_FILENO; | fd = STDIN_FILENO; | ||||
else { | else if ((fd = open(file, O_RDONLY, 0)) < 0) { | ||||
if ((fd = open(file, O_RDONLY, 0)) < 0) { | |||||
xo_warn("%s: open", file); | xo_warn("%s: open", file); | ||||
return (1); | return (1); | ||||
} | } | ||||
if (doword || (domulti && MB_CUR_MAX != 1)) | if (!(doword || (domulti && MB_CUR_MAX != 1))) { | ||||
goto word; | |||||
/* | /* | ||||
* Line counting is split out because it's a lot faster to get | * Line counting is split out because it's a lot faster to get | ||||
* lines than to get words, since the word count requires some | * lines than to get words, since the word count requires some | ||||
* logic. | * logic. | ||||
*/ | */ | ||||
if (doline) { | if (doline) { | ||||
while ((len = read(fd, buf, MAXBSIZE))) { | while ((len = read(fd, buf, MAXBSIZE))) { | ||||
if (len == -1) { | if (len == -1) { | ||||
xo_warn("%s: read", file); | xo_warn("%s: read", file != NULL ? file : "stdin"); | ||||
(void)close(fd); | (void)close(fd); | ||||
return (1); | return (1); | ||||
} | } | ||||
if (siginfo) { | if (siginfo) { | ||||
show_cnt(file, linect, wordct, charct, | show_cnt(file, linect, wordct, charct, | ||||
llct); | llct); | ||||
} | } | ||||
charct += len; | charct += len; | ||||
if (dolongline) { | |||||
for (p = buf; len--; ++p) | for (p = buf; len--; ++p) | ||||
if (*p == '\n') { | if (*p == '\n') { | ||||
if (tmpll > llct) | if (tmpll > llct) | ||||
llct = tmpll; | llct = tmpll; | ||||
tmpll = 0; | tmpll = 0; | ||||
++linect; | ++linect; | ||||
} else | } else | ||||
tmpll++; | tmpll++; | ||||
} else | |||||
linect += count_newlines(buf, len); | |||||
} | } | ||||
reset_siginfo(); | reset_siginfo(); | ||||
tlinect += linect; | tlinect += linect; | ||||
if (dochar) | if (dochar) | ||||
tcharct += charct; | tcharct += charct; | ||||
if (dolongline) { | if (dolongline) { | ||||
if (llct > tlongline) | if (llct > tlongline) | ||||
tlongline = llct; | tlongline = llct; | ||||
} | } | ||||
show_cnt(file, linect, wordct, charct, llct); | show_cnt(file, linect, wordct, charct, llct); | ||||
(void)close(fd); | (void)close(fd); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* If all we need is the number of characters and it's a | * If all we need is the number of characters and it's a | ||||
* regular file, just stat the puppy. | * regular file, just stat the puppy. | ||||
*/ | */ | ||||
if (dochar || domulti) { | if (dochar || domulti) { | ||||
if (fstat(fd, &sb)) { | if (fstat(fd, &sb)) { | ||||
xo_warn("%s: fstat", file); | xo_warn("%s: fstat", file != NULL ? file : "stdin"); | ||||
(void)close(fd); | (void)close(fd); | ||||
return (1); | return (1); | ||||
} | } | ||||
if (S_ISREG(sb.st_mode)) { | if (S_ISREG(sb.st_mode)) { | ||||
reset_siginfo(); | reset_siginfo(); | ||||
charct = sb.st_size; | charct = sb.st_size; | ||||
show_cnt(file, linect, wordct, charct, llct); | show_cnt(file, linect, wordct, charct, llct); | ||||
tcharct += charct; | tcharct += charct; | ||||
(void)close(fd); | (void)close(fd); | ||||
return (0); | return (0); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
/* Do it the hard way... */ | /* Do it the hard way... */ | ||||
word: gotsp = 1; | gotsp = 1; | ||||
warned = 0; | warned = 0; | ||||
memset(&mbs, 0, sizeof(mbs)); | memset(&mbs, 0, sizeof(mbs)); | ||||
while ((len = read(fd, buf, MAXBSIZE)) != 0) { | while ((len = read(fd, buf, MAXBSIZE)) != 0) { | ||||
if (len == -1) { | if (len == -1) { | ||||
xo_warn("%s: read", file != NULL ? file : "stdin"); | xo_warn("%s: read", file != NULL ? file : "stdin"); | ||||
(void)close(fd); | (void)close(fd); | ||||
return (1); | return (1); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 66 Lines • Show Last 20 Lines |