initial commit
This commit is contained in:
commit
8e26716a5a
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT/X Consortium License
|
||||
|
||||
© 2011 Connor Lane Smith <cls@lubutu.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
31
Makefile
Normal file
31
Makefile
Normal file
|
@ -0,0 +1,31 @@
|
|||
include config.mk
|
||||
|
||||
SRC = basename.c cat.c echo.c false.c grep.c tee.c touch.c true.c wc.c
|
||||
OBJ = $(SRC:.c=.o) util.o
|
||||
BIN = $(SRC:.c=)
|
||||
MAN = $(SRC:.c=.1)
|
||||
|
||||
all: $(BIN)
|
||||
|
||||
$(OBJ): util.h
|
||||
$(BIN): util.o
|
||||
|
||||
.o:
|
||||
@echo CC -o $@
|
||||
@$(CC) -o $@ $< util.o $(LDFLAGS)
|
||||
|
||||
.c.o:
|
||||
@echo CC -c $<
|
||||
@$(CC) -c $< $(CFLAGS)
|
||||
|
||||
dist: clean
|
||||
@echo creating dist tarball
|
||||
@mkdir -p sbase-$(VERSION)
|
||||
@cp LICENSE Makefile config.mk $(SRC) $(MAN) util.c util.h sbase-$(VERSION)
|
||||
@tar -cf sbase-$(VERSION).tar sbase-$(VERSION)
|
||||
@gzip sbase-$(VERSION).tar
|
||||
@rm -rf sbase-$(VERSION)
|
||||
|
||||
clean:
|
||||
@echo cleaning
|
||||
@rm -f $(BIN) $(OBJ)
|
14
basename.1
Normal file
14
basename.1
Normal file
|
@ -0,0 +1,14 @@
|
|||
.TH BASENAME 1 sbase\-VERSION
|
||||
.SH NAME
|
||||
basename \- strip directory from filename
|
||||
.SH SYNOPSIS
|
||||
.B basename
|
||||
.I string
|
||||
.RI [ suffix ]
|
||||
.SH DESCRIPTION
|
||||
.B basename
|
||||
prints to stdout the
|
||||
.I string
|
||||
with any leading directory components, and the
|
||||
.IR suffix ,
|
||||
removed.
|
30
basename.c
Normal file
30
basename.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/* See LICENSE file for copyright and license details. */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "util.h"
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char *str = argv[1];
|
||||
size_t n, i = 0;
|
||||
|
||||
if(argc < 2)
|
||||
eprintf("usage: %s string [suffix]\n", argv[0]);
|
||||
if(str[0] != '\0')
|
||||
for(i = strlen(str)-1; i > 0 && str[i] == '/'; i--)
|
||||
str[i] = '\0';
|
||||
if(i == 0 || !(str = strrchr(argv[1], '/')))
|
||||
str = argv[1];
|
||||
else
|
||||
str++;
|
||||
|
||||
if(argc > 2 && strlen(str) > strlen(argv[2])) {
|
||||
n = strlen(str) - strlen(argv[2]);
|
||||
if(!strcmp(&str[n], argv[2]))
|
||||
str[n] = '\0';
|
||||
}
|
||||
puts(str);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
10
cat.1
Normal file
10
cat.1
Normal file
|
@ -0,0 +1,10 @@
|
|||
.TH CAT 1 sbase\-VERSION
|
||||
.SH NAME
|
||||
cat \- concatenate files
|
||||
.SH SYNOPSIS
|
||||
.B cat
|
||||
.RI [ files ...]
|
||||
.SH DESCRIPTION
|
||||
.B cat
|
||||
reads each file in sequence and writes it to stdout. If no file is given, cat
|
||||
reads from stdin.
|
36
cat.c
Normal file
36
cat.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/* See LICENSE file for copyright and license details. */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "util.h"
|
||||
|
||||
static void cat(FILE *, const char *);
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
FILE *fp;
|
||||
|
||||
if(argc == 1)
|
||||
cat(stdin, "<stdin>");
|
||||
else for(i = 1; i < argc; i++) {
|
||||
if(!(fp = fopen(argv[i], "r")))
|
||||
eprintf("fopen %s:", argv[i]);
|
||||
cat(fp, argv[i]);
|
||||
fclose(fp);
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
cat(FILE *fp, const char *str)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
size_t n;
|
||||
|
||||
while((n = fread(buf, 1, sizeof buf, fp)) > 0)
|
||||
if(fwrite(buf, 1, n, stdout) != n)
|
||||
eprintf("<stdout>: write error:");
|
||||
if(ferror(fp))
|
||||
eprintf("%s: read error:", str);
|
||||
}
|
9
config.mk
Normal file
9
config.mk
Normal file
|
@ -0,0 +1,9 @@
|
|||
# sbase version
|
||||
VERSION = 0.0
|
||||
|
||||
CC = cc
|
||||
#CC = musl-gcc
|
||||
|
||||
CPPFLAGS = -D_BSD_SOURCE
|
||||
CFLAGS = -Os -ansi -Wall -pedantic $(CPPFLAGS)
|
||||
LDFLAGS = -s -static
|
14
echo.1
Normal file
14
echo.1
Normal file
|
@ -0,0 +1,14 @@
|
|||
.TH ECHO 1 sbase\-VERSION
|
||||
.SH NAME
|
||||
echo \- print arguments
|
||||
.SH SYNOPSIS
|
||||
.B echo
|
||||
.RB [ \-n ]
|
||||
.RI [ string ...]
|
||||
.SH DESCRIPTION
|
||||
.B echo
|
||||
prints its arguments to stdout, separated by spaces and terminated by a newline.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-n
|
||||
Do not print terminating newline.
|
23
echo.c
Normal file
23
echo.c
Normal file
|
@ -0,0 +1,23 @@
|
|||
/* See LICENSE file for copyright and license details. */
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
bool nflag = false;
|
||||
int i;
|
||||
|
||||
if(argc > 1 && !strcmp(argv[1], "-n"))
|
||||
nflag = true;
|
||||
for(i = nflag ? 2 : 1; i < argc; i++) {
|
||||
fputs(argv[i], stdout);
|
||||
if(i+1 < argc)
|
||||
fputc(' ', stdout);
|
||||
}
|
||||
if(!nflag)
|
||||
fputc('\n', stdout);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
8
false.1
Normal file
8
false.1
Normal file
|
@ -0,0 +1,8 @@
|
|||
.TH FALSE 1 sbase\-VERSION
|
||||
.SH NAME
|
||||
false \- return failure
|
||||
.SH SYNOPSIS
|
||||
.B false
|
||||
.SH DESCRIPTION
|
||||
.B false
|
||||
returns with a status code indicating failure.
|
8
false.c
Normal file
8
false.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
/* See LICENSE file for copyright and license details. */
|
||||
#include <stdlib.h>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
43
grep.1
Normal file
43
grep.1
Normal file
|
@ -0,0 +1,43 @@
|
|||
.TH GREP 1 sbase\-VERSION
|
||||
.SH NAME
|
||||
grep \- search files for a pattern
|
||||
.SH SYNOPSIS
|
||||
.B grep
|
||||
.RB [ \-c ]
|
||||
.RB [ \-i ]
|
||||
.RB [ \-l ]
|
||||
.RB [ \-n ]
|
||||
.RB [ \-q ]
|
||||
.RB [ \-v ]
|
||||
.I pattern
|
||||
.RI [ file ...]
|
||||
.SH DESCRIPTION
|
||||
.B grep
|
||||
searches the input files for lines that match the pattern, a regular expression as defined in
|
||||
.BR regex (7).
|
||||
By default each matching line is printed to stdout. If no file is given, grep
|
||||
reads from stdin.
|
||||
.P
|
||||
The status code is 0 if any lines match, and 1 if not. If an error occurred the
|
||||
status code is 2.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-c
|
||||
prints only a count of matching lines.
|
||||
.TP
|
||||
.B \-i
|
||||
matches lines case insensitively.
|
||||
.TP
|
||||
.B \-l
|
||||
prints only the names of files with matching lines.
|
||||
.TP
|
||||
.B \-n
|
||||
prefixes each matching line with its line number in the input.
|
||||
.TP
|
||||
.B \-q
|
||||
prints nothing, only returns status.
|
||||
.TP
|
||||
.B \-v
|
||||
selects lines which do
|
||||
.B not
|
||||
match the pattern.
|
97
grep.c
Normal file
97
grep.c
Normal file
|
@ -0,0 +1,97 @@
|
|||
/* See LICENSE file for copyright and license details. */
|
||||
#include <regex.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static void grep(FILE *, const char *, regex_t *);
|
||||
|
||||
static bool iflag = false;
|
||||
static bool vflag = false;
|
||||
static bool many;
|
||||
static bool match = false;
|
||||
static char mode = 0;
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i, flags = 0;
|
||||
regex_t preg;
|
||||
FILE *fp;
|
||||
|
||||
for(i = 1; i < argc; i++)
|
||||
if(!strcmp(argv[i], "-c"))
|
||||
mode = 'c';
|
||||
else if(!strcmp(argv[i], "-i"))
|
||||
iflag = true;
|
||||
else if(!strcmp(argv[i], "-l"))
|
||||
mode = 'l';
|
||||
else if(!strcmp(argv[i], "-n"))
|
||||
mode = 'n';
|
||||
else if(!strcmp(argv[i], "-q"))
|
||||
mode = 'q';
|
||||
else if(!strcmp(argv[i], "-v"))
|
||||
vflag = true;
|
||||
else
|
||||
break;
|
||||
|
||||
if(i == argc) {
|
||||
fprintf(stderr, "usage: %s [-c] [-i] [-l] [-n] [-v] pattern [files...]\n", argv[0]);
|
||||
exit(2);
|
||||
}
|
||||
if(mode == 'c')
|
||||
flags |= REG_NOSUB;
|
||||
if(iflag)
|
||||
flags |= REG_ICASE;
|
||||
regcomp(&preg, argv[i++], flags);
|
||||
|
||||
many = (argc > i+1);
|
||||
if(i == argc)
|
||||
grep(stdin, "<stdin>", &preg);
|
||||
else for(; i < argc; i++) {
|
||||
if(!(fp = fopen(argv[i], "r"))) {
|
||||
fprintf(stderr, "fopen %s: ", argv[i]);
|
||||
perror(NULL);
|
||||
exit(2);
|
||||
}
|
||||
grep(fp, argv[i], &preg);
|
||||
fclose(fp);
|
||||
}
|
||||
return match ? 0 : 1;
|
||||
}
|
||||
|
||||
void
|
||||
grep(FILE *fp, const char *str, regex_t *preg)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
int n, c = 0;
|
||||
|
||||
for(n = 1; fgets(buf, sizeof buf, fp); n++) {
|
||||
if(regexec(preg, buf, 0, NULL, 0) ^ vflag)
|
||||
continue;
|
||||
if(mode == 'c')
|
||||
c++;
|
||||
else if(mode == 'l') {
|
||||
puts(str);
|
||||
break;
|
||||
}
|
||||
else if(mode == 'q')
|
||||
exit(0);
|
||||
else {
|
||||
if(many)
|
||||
printf("%s:", str);
|
||||
if(mode == 'n')
|
||||
printf("%d:", n);
|
||||
fputs(buf, stdout);
|
||||
}
|
||||
match = true;
|
||||
}
|
||||
if(mode == 'c')
|
||||
printf("%d\n", c);
|
||||
if(ferror(fp)) {
|
||||
fprintf(stderr, "%s: read error: ", str);
|
||||
perror(NULL);
|
||||
exit(2);
|
||||
}
|
||||
}
|
14
tee.1
Normal file
14
tee.1
Normal file
|
@ -0,0 +1,14 @@
|
|||
.TH TEE 1 sbase\-VERSION
|
||||
.SH NAME
|
||||
tee \- duplicate stdin
|
||||
.SH SYNOPSIS
|
||||
.B tee
|
||||
.RB [ \-a ]
|
||||
.RI [ file ...]
|
||||
.SH DESCRIPTION
|
||||
.B tee
|
||||
writes from stdin to stdout, making copies in each file.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-a
|
||||
append to each file rather than overwriting.
|
36
tee.c
Normal file
36
tee.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/* See LICENSE file for copyright and license details. */
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "util.h"
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
bool aflag = false;
|
||||
char buf[BUFSIZ];
|
||||
int i, nfps = 1;
|
||||
size_t n;
|
||||
FILE **fps;
|
||||
|
||||
if(argc > 1 && !strcmp(argv[1], "-a"))
|
||||
aflag = true;
|
||||
if(!(fps = malloc(sizeof *fps)))
|
||||
eprintf("malloc:");
|
||||
fps[nfps-1] = stdout;
|
||||
|
||||
for(i = aflag ? 2 : 1; i < argc; i++) {
|
||||
if(!(fps = realloc(fps, ++nfps * sizeof *fps)))
|
||||
eprintf("realloc:");
|
||||
if(!(fps[nfps-1] = fopen(argv[i], aflag ? "a" : "w")))
|
||||
eprintf("fopen %s:", argv[i]);
|
||||
}
|
||||
while((n = fread(buf, 1, sizeof buf, stdin)) > 0)
|
||||
for(i = 0; i < nfps; i++)
|
||||
if(fwrite(buf, 1, n, fps[i]) != n)
|
||||
eprintf("%s: write error:", buf);
|
||||
if(ferror(stdin))
|
||||
eprintf("<stdin>: read error:");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
22
touch.1
Normal file
22
touch.1
Normal file
|
@ -0,0 +1,22 @@
|
|||
.TH TOUCH 1 sbase\-VERSION
|
||||
.SH NAME
|
||||
touch \- set files' modification time
|
||||
.SH SYNOPSIS
|
||||
.B touch
|
||||
.RB [ \-c ]
|
||||
.RB [ \-t
|
||||
.IR time ]
|
||||
.RI [ file ...]
|
||||
.SH DESCRIPTION
|
||||
.B touch
|
||||
sets the files' modification time to the current time. If a file does not exist
|
||||
it is created.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-c
|
||||
do not create files if they do not exist.
|
||||
.TP
|
||||
.BI \-t " time"
|
||||
sets the files' modification time to
|
||||
.IR time ,
|
||||
given as the number of seconds since the Unix epoch.
|
58
touch.c
Normal file
58
touch.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* See LICENSE file for copyright and license details. */
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <utime.h>
|
||||
#include <sys/stat.h>
|
||||
#include "util.h"
|
||||
|
||||
static void touch(const char *);
|
||||
|
||||
static bool cflag = false;
|
||||
static time_t t;
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
t = time(NULL);
|
||||
|
||||
for(i = 1; i < argc; i++)
|
||||
if(!strcmp(argv[i], "-c"))
|
||||
cflag = true;
|
||||
else if(!strcmp(argv[i], "-t") && i+1 < argc)
|
||||
t = strtol(argv[++i], NULL, 0);
|
||||
else
|
||||
break;
|
||||
|
||||
for(; i < argc; i++)
|
||||
touch(argv[i]);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
touch(const char *str)
|
||||
{
|
||||
int fd;
|
||||
struct stat st;
|
||||
struct utimbuf ut;
|
||||
|
||||
if(stat(str, &st) < 0) {
|
||||
if(errno != ENOENT)
|
||||
eprintf("stat %s:", str);
|
||||
if(cflag)
|
||||
return;
|
||||
if((fd = creat(str, O_RDONLY|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0)
|
||||
eprintf("creat %s:", str);
|
||||
close(fd);
|
||||
}
|
||||
ut.actime = st.st_atime;
|
||||
ut.modtime = t;
|
||||
if(utime(str, &ut) < 0)
|
||||
eprintf("utime %s:", str);
|
||||
}
|
8
true.1
Normal file
8
true.1
Normal file
|
@ -0,0 +1,8 @@
|
|||
.TH TRUE 1 sbase\-VERSION
|
||||
.SH NAME
|
||||
true \- return success
|
||||
.SH SYNOPSIS
|
||||
.B true
|
||||
.SH DESCRIPTION
|
||||
.B true
|
||||
returns with a status code indicating success.
|
8
true.c
Normal file
8
true.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
/* See LICENSE file for copyright and license details. */
|
||||
#include <stdlib.h>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
}
|
22
util.c
Normal file
22
util.c
Normal file
|
@ -0,0 +1,22 @@
|
|||
/* See LICENSE file for copyright and license details. */
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "util.h"
|
||||
|
||||
void
|
||||
eprintf(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if(fmt[0] && fmt[strlen(fmt)-1] == ':') {
|
||||
fputc(' ', stderr);
|
||||
perror(NULL);
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
3
util.h
Normal file
3
util.h
Normal file
|
@ -0,0 +1,3 @@
|
|||
/* See LICENSE file for copyright and license details. */
|
||||
|
||||
void eprintf(const char *, ...);
|
28
wc.1
Normal file
28
wc.1
Normal file
|
@ -0,0 +1,28 @@
|
|||
.TH WC 1 sbase\-VERSION
|
||||
.SH NAME
|
||||
wc \- word count
|
||||
.SH SYNOPSIS
|
||||
.B wc
|
||||
.RB [ \-c ]
|
||||
.RB [ \-l ]
|
||||
.RB [ \-m ]
|
||||
.RB [ \-w ]
|
||||
.RI [ file ...]
|
||||
.SH DESCRIPTION
|
||||
.B wc
|
||||
prints the number of lines, words, and bytes in each file. If any flags are
|
||||
given, wc will print only the requested information. If no files are given, wc
|
||||
reads stdin.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-c
|
||||
print the number of bytes.
|
||||
.TP
|
||||
.B \-l
|
||||
print the number of lines.
|
||||
.TP
|
||||
.B \-m
|
||||
print the number of characters, not bytes.
|
||||
.TP
|
||||
.B \-w
|
||||
print the number of words.
|
89
wc.c
Normal file
89
wc.c
Normal file
|
@ -0,0 +1,89 @@
|
|||
/* See LICENSE file for copyright and license details. */
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "util.h"
|
||||
|
||||
static void output(const char *, long, long, long);
|
||||
static void wc(FILE *, const char *);
|
||||
|
||||
static bool lflag = false;
|
||||
static bool wflag = false;
|
||||
static char cmode = 0;
|
||||
static long tc = 0, tl = 0, tw = 0;
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
bool many;
|
||||
int i;
|
||||
FILE *fp;
|
||||
|
||||
for(i = 1; i < argc; i++)
|
||||
if(!strcmp(argv[i], "-c"))
|
||||
cmode = 'c';
|
||||
else if(!strcmp(argv[i], "-l"))
|
||||
lflag = true;
|
||||
else if(!strcmp(argv[i], "-m"))
|
||||
cmode = 'm';
|
||||
else if(!strcmp(argv[i], "-w"))
|
||||
wflag = true;
|
||||
else
|
||||
break;
|
||||
many = (argc > i+1);
|
||||
|
||||
if(i == argc)
|
||||
wc(stdin, NULL);
|
||||
else for(; i < argc; i++) {
|
||||
if(!(fp = fopen(argv[i], "r")))
|
||||
eprintf("fopen %s:", argv[i]);
|
||||
wc(fp, argv[i]);
|
||||
fclose(fp);
|
||||
}
|
||||
if(many)
|
||||
output("total", tc, tl, tw);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
output(const char *str, long nc, long nl, long nw)
|
||||
{
|
||||
bool noflags = !cmode && !lflag && !wflag;
|
||||
|
||||
if(lflag || noflags)
|
||||
printf(" %5ld", nl);
|
||||
if(wflag || noflags)
|
||||
printf(" %5ld", nw);
|
||||
if(cmode || noflags)
|
||||
printf(" %5ld", nc);
|
||||
if(str)
|
||||
printf(" %s", str);
|
||||
fputc('\n', stdout);
|
||||
}
|
||||
|
||||
void
|
||||
wc(FILE *fp, const char *str)
|
||||
{
|
||||
bool word = false;
|
||||
char c;
|
||||
long nc = 0, nl = 0, nw = 0;
|
||||
|
||||
while((c = fgetc(fp)) != EOF) {
|
||||
if(cmode != 'm' || (c & 0xc0) != 0x80)
|
||||
nc++;
|
||||
if(c == '\n')
|
||||
nl++;
|
||||
if(!isspace(c))
|
||||
word = true;
|
||||
else if(word) {
|
||||
word = false;
|
||||
nw++;
|
||||
}
|
||||
}
|
||||
tc += nc;
|
||||
tl += nl;
|
||||
tw += nw;
|
||||
output(str, nc, nl, nw);
|
||||
}
|
Loading…
Reference in New Issue
Block a user