version 1.2, 1996/06/26 05:42:50 |
version 1.3, 1999/02/02 03:44:07 |
|
|
/* $OpenBSD$ */ |
/* $OpenBSD$ */ |
|
|
/* |
/* |
* Copyright (c) 1980, 1987 Regents of the University of California. |
* Copyright (c) 1980, 1987, 1991, 1993 |
* All rights reserved. |
* The Regents of the University of California. All rights reserved. |
* |
* |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* modification, are permitted provided that the following conditions |
|
|
*/ |
*/ |
|
|
#ifndef lint |
#ifndef lint |
char copyright[] = |
static char copyright[] = |
"@(#) Copyright (c) 1980, 1987 Regents of the University of California.\n\ |
"@(#) Copyright (c) 1980, 1987, 1991, 1993\n\ |
All rights reserved.\n"; |
The Regents of the University of California. All rights reserved.\n"; |
#endif /* not lint */ |
#endif /* not lint */ |
|
|
#ifndef lint |
#ifndef lint |
/*static char sccsid[] = "from: @(#)wc.c 5.7 (Berkeley) 3/2/91";*/ |
#if 0 |
|
static char sccsid[] = "@(#)wc.c 8.2 (Berkeley) 5/2/95"; |
|
#else |
static char rcsid[] = "$OpenBSD$"; |
static char rcsid[] = "$OpenBSD$"; |
|
#endif |
#endif /* not lint */ |
#endif /* not lint */ |
|
|
/* wc line, word and char count */ |
|
|
|
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
#include <locale.h> |
#include <locale.h> |
#include <ctype.h> |
#include <ctype.h> |
#include <errno.h> |
#include <err.h> |
#include <sys/param.h> |
#include <sys/param.h> |
#include <sys/stat.h> |
#include <sys/stat.h> |
#include <sys/file.h> |
#include <sys/file.h> |
#include <unistd.h> |
#include <unistd.h> |
#include <err.h> |
|
|
|
static void print_counts(); |
int64_t tlinect, twordct, tcharct; |
static void cnt(); |
int doline, doword, dochar; |
static long tlinect, twordct, tcharct; |
int rval; |
static int doline, doword, dochar; |
extern char *__progname; |
static int rval = 0; |
|
|
|
|
void print_counts __P((int64_t, int64_t, int64_t, char *)); |
|
void cnt __P((char *)); |
|
|
int |
int |
main(argc, argv) |
main(argc, argv) |
int argc; |
int argc; |
char **argv; |
char *argv[]; |
{ |
{ |
extern int optind; |
|
register int ch; |
register int ch; |
|
|
setlocale(LC_ALL, ""); |
setlocale(LC_ALL, ""); |
|
|
break; |
break; |
case '?': |
case '?': |
default: |
default: |
fprintf(stderr, "usage: wc [-c | -m] [-lw] [file ...]\n"); |
(void)fprintf(stderr, |
|
"usage: %s [-c | -m] [-lw] [file ...]\n", |
|
__progname); |
exit(1); |
exit(1); |
} |
} |
argv += optind; |
argv += optind; |
|
|
* if you don't get any arguments, you have to turn them |
* if you don't get any arguments, you have to turn them |
* all on. |
* all on. |
*/ |
*/ |
if (!doline && !doword && !dochar) { |
if (!doline && !doword && !dochar) |
doline = doword = dochar = 1; |
doline = doword = dochar = 1; |
} |
|
|
|
if (!*argv) { |
if (!*argv) { |
cnt((char *)NULL); |
cnt((char *)NULL); |
|
|
cnt(*argv); |
cnt(*argv); |
} while(*++argv); |
} while(*++argv); |
|
|
if (dototal) { |
if (dototal) |
print_counts (tlinect, twordct, tcharct, "total"); |
print_counts(tlinect, twordct, tcharct, "total"); |
} |
|
} |
} |
|
|
exit(rval); |
exit(rval); |
} |
} |
|
|
|
void |
static void |
|
cnt(file) |
cnt(file) |
char *file; |
char *file; |
{ |
{ |
register u_char *C; |
register u_char *C; |
register short gotsp; |
register short gotsp; |
register int len; |
register int len; |
register long linect, wordct, charct; |
register int64_t linect, wordct, charct; |
struct stat sbuf; |
struct stat sbuf; |
int fd; |
int fd; |
u_char buf[MAXBSIZE]; |
u_char buf[MAXBSIZE]; |
|
|
linect = wordct = charct = 0; |
linect = wordct = charct = 0; |
if (file) { |
if (file) { |
if ((fd = open(file, O_RDONLY, 0)) < 0) { |
if ((fd = open(file, O_RDONLY, 0)) < 0) { |
warn ("%s", file); |
warn("%s", file); |
rval = 1; |
rval = 1; |
return; |
return; |
} |
} |
|
|
|
|
if (!doword) { |
if (!doword) { |
/* |
/* |
* line counting is split out because it's a lot |
* Line counting is split out because it's a lot |
* faster to get lines than to get words, since |
* faster to get lines than to get words, since |
* the word count requires some logic. |
* the word count requires some logic. |
*/ |
*/ |
if (doline) { |
if (doline) { |
while((len = read(fd, buf, MAXBSIZE)) > 0) { |
while ((len = read(fd, buf, MAXBSIZE)) > 0) { |
charct += len; |
charct += len; |
for (C = buf; len--; ++C) |
for (C = buf; len--; ++C) |
if (*C == '\n') |
if (*C == '\n') |
++linect; |
++linect; |
} |
} |
if (len == -1) { |
if (len == -1) { |
warn ("%s", file); |
warn("%s", file); |
rval = 1; |
rval = 1; |
} |
} |
} |
} |
|
|
/* |
/* |
* if all we need is the number of characters and |
* If all we need is the number of characters and |
* it's a directory or a regular or linked file, just |
* it's a directory or a regular or linked file, just |
* stat the puppy. We avoid testing for it not being |
* stat the puppy. We avoid testing for it not being |
* a special device in case someone adds a new type |
* a special device in case someone adds a new type |
* of inode. |
* of inode. |
*/ |
*/ |
else if (dochar) { |
else if (dochar) { |
int ifmt; |
mode_t ifmt; |
|
|
if (fstat(fd, &sbuf)) { |
if (fstat(fd, &sbuf)) { |
warn ("%s", file); |
warn("%s", file); |
rval = 1; |
rval = 1; |
} else { |
} else { |
ifmt = sbuf.st_mode & S_IFMT; |
ifmt = sbuf.st_mode & S_IFMT; |
if (ifmt == S_IFREG || ifmt == S_IFLNK |
if (ifmt == S_IFREG || ifmt == S_IFLNK |
|| ifmt == S_IFDIR) { |
|| ifmt == S_IFDIR) { |
charct = sbuf.st_size; |
charct = sbuf.st_size; |
} else { |
} else { |
while((len = read(fd, buf, MAXBSIZE)) > 0) |
while ((len = read(fd, buf, MAXBSIZE)) > 0) |
charct += len; |
charct += len; |
if (len == -1) { |
if (len == -1) { |
warn ("%s", file); |
warn("%s", file); |
rval = 1; |
rval = 1; |
} |
} |
} |
} |
} |
} |
} |
} |
} |
} else { |
else |
/* Do it the hard way... */ |
{ |
|
/* do it the hard way... */ |
|
gotsp = 1; |
gotsp = 1; |
while ((len = read(fd, buf, MAXBSIZE)) > 0) { |
while ((len = read(fd, buf, MAXBSIZE)) > 0) { |
|
/* |
|
* This loses in the presence of multi-byte characters. |
|
* To do it right would require a function to return a |
|
* character while knowing how many bytes it consumed. |
|
*/ |
charct += len; |
charct += len; |
for (C = buf; len--; ++C) { |
for (C = buf; len--; ++C) { |
if (isspace (*C)) { |
if (isspace (*C)) { |
gotsp = 1; |
gotsp = 1; |
if (*C == '\n') { |
if (*C == '\n') |
++linect; |
++linect; |
} |
|
} else { |
} else { |
/* |
/* |
* This line implements the POSIX |
* This line implements the POSIX |
|
|
} |
} |
} |
} |
if (len == -1) { |
if (len == -1) { |
warn ("%s", file); |
warn("%s", file); |
rval = 1; |
rval = 1; |
} |
} |
} |
} |
|
|
print_counts (linect, wordct, charct, file ? file : ""); |
print_counts(linect, wordct, charct, file ? file : ""); |
|
|
/* don't bother checkint doline, doword, or dochar --- speeds |
/* |
up the common case */ |
* Don't bother checking doline, doword, or dochar -- speeds |
|
* up the common case |
|
*/ |
tlinect += linect; |
tlinect += linect; |
twordct += wordct; |
twordct += wordct; |
tcharct += charct; |
tcharct += charct; |
|
|
if (close(fd)) { |
if (close(fd) != 0) { |
warn ("%s", file); |
warn("%s", file); |
rval = 1; |
rval = 1; |
} |
} |
} |
} |
|
|
|
|
void |
void |
print_counts (lines, words, chars, name) |
print_counts(lines, words, chars, name) |
long lines; |
int64_t lines; |
long words; |
int64_t words; |
long chars; |
int64_t chars; |
char *name; |
char *name; |
{ |
{ |
|
|
if (doline) |
if (doline) |
printf(" %7ld", lines); |
(void)printf(" %7qd", (quad_t) lines); |
if (doword) |
if (doword) |
printf(" %7ld", words); |
(void)printf(" %7qd", (quad_t) words); |
if (dochar) |
if (dochar) |
printf(" %7ld", chars); |
(void)printf(" %7qd", (quad_t) chars); |
|
|
printf (" %s\n", name); |
(void)printf(" %s\n", name); |
} |
} |