Update Makefile. Finish wc.
parent
d8bb1fcc3e
commit
8783d7f5fc
|
@ -22,7 +22,7 @@ false: true
|
|||
install: all
|
||||
install -Dm0755 ${BIN} ${DESTDIR}/${PREFIX}/bin
|
||||
|
||||
clean: all
|
||||
clean:
|
||||
rm ${BIN} *.o
|
||||
|
||||
check:
|
||||
|
|
|
@ -88,3 +88,34 @@ char *mastrcat(char *str1, char *str2)
|
|||
return nbuf;
|
||||
}
|
||||
|
||||
/* open stdin if path is null */
|
||||
FILE *file_open(char *path, char *mode)
|
||||
{
|
||||
FILE *fd;
|
||||
|
||||
fd = 0;
|
||||
|
||||
|
||||
if(!mode)
|
||||
{
|
||||
throw(MISC_FAIL, "file_open: mode is null. Terminating.");
|
||||
}
|
||||
|
||||
if(path == NULL || !strcmp(path, "-"))
|
||||
{
|
||||
fd = fopen("/dev/stdin", mode);
|
||||
}
|
||||
else
|
||||
{
|
||||
fd = fopen(path, mode);
|
||||
}
|
||||
|
||||
if(!fd)
|
||||
{
|
||||
throw(FOPEN_FAIL, mastrcat("file_open: couldn't open ", mastrcat(path, mastrcat(" using mode ", mode))));
|
||||
}
|
||||
|
||||
|
||||
return(fd);
|
||||
}
|
||||
|
||||
|
|
217
src/wc.c
217
src/wc.c
|
@ -9,117 +9,184 @@
|
|||
#include "support.h"
|
||||
|
||||
|
||||
/* Parameters */
|
||||
enum
|
||||
{
|
||||
C,
|
||||
M,
|
||||
L,
|
||||
W,
|
||||
L,
|
||||
CM
|
||||
};
|
||||
|
||||
/* States */
|
||||
enum {
|
||||
OUTWORD,
|
||||
INWORD,
|
||||
INWORD
|
||||
};
|
||||
|
||||
/* Category names for count[] and result[] */
|
||||
enum {
|
||||
/* character or byte */
|
||||
COB = 0,
|
||||
WORDS = 1,
|
||||
LINES = 2,
|
||||
LINES,
|
||||
WORDS,
|
||||
COB
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
int wc(FILE *fd, int *results)
|
||||
{
|
||||
char state;
|
||||
int c, i;
|
||||
|
||||
char par[4] = {1};
|
||||
/* M and C conflict; M counts actual characters (theoretically), so we should go with that as the default */
|
||||
par[C] = 0;
|
||||
int count[3] = {0};
|
||||
int total[3] = {0};
|
||||
FILE *fd;
|
||||
int c;
|
||||
|
||||
state = OUTWORD;
|
||||
c = i = 0;
|
||||
c = 0;
|
||||
|
||||
|
||||
for(c = 0; (c = fgetc(fd)) != EOF;)
|
||||
{
|
||||
if(!(isblank(c) || c == '\n'))
|
||||
{
|
||||
if(state == OUTWORD)
|
||||
{
|
||||
results[WORDS]++;
|
||||
}
|
||||
|
||||
state = INWORD;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(c == '\n')
|
||||
{
|
||||
results[LINES]++;
|
||||
}
|
||||
|
||||
state = OUTWORD;
|
||||
}
|
||||
|
||||
results[COB]++;
|
||||
}
|
||||
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* if a particular pars element is non-zero, print the corresponding total element. */
|
||||
/* if pars is NULL, print everything */
|
||||
/* if total is NULL, throw an error */
|
||||
int printres(int *total, char *filepath, char *pars)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
|
||||
|
||||
if(!total)
|
||||
{
|
||||
throw(MISC_FAIL, "printres: total is null");
|
||||
}
|
||||
|
||||
|
||||
for(i = 0; i <= 2; i++)
|
||||
{
|
||||
if(pars == NULL || pars[i])
|
||||
{
|
||||
printf("%d ", total[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if(filepath)
|
||||
{
|
||||
if(!strcmp("-", filepath))
|
||||
{
|
||||
printf("stdin");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%s", filepath);
|
||||
}
|
||||
}
|
||||
putchar('\n');
|
||||
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
/* haspar == 0 means we pass NULL to printres for default POSIX behavior */
|
||||
char haspar;
|
||||
int c, i;
|
||||
int current[3] = {0};
|
||||
int results[3] = {0};
|
||||
|
||||
char pars[3] = {0};
|
||||
FILE *fd;
|
||||
|
||||
haspar = 0;
|
||||
/* c value is arbitrary but is non-NULL for safety reasons; i is used to ensure the program does not open itself */
|
||||
c = i = 1;
|
||||
|
||||
fd = 0;
|
||||
|
||||
|
||||
|
||||
/* process our parameters */
|
||||
for(; (c = getopt(argc, argv, "cmlw")) != -1; c = 0)
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case 'c': par[C] = 1;
|
||||
par[M] = 0;
|
||||
case 'c': pars[CM] = 1;
|
||||
haspar = 1;
|
||||
break;
|
||||
case 'm': par[M] = 1;
|
||||
par[C] = 0;
|
||||
case 'm': pars[CM] = -1;
|
||||
haspar = 1;
|
||||
break;
|
||||
case 'l': par[L] = 1;
|
||||
case 'l': pars[L] = 1;
|
||||
haspar = 1;
|
||||
break;
|
||||
case 'w': par[W] = 1;
|
||||
case 'w': pars[W] = 1;
|
||||
haspar = 1;
|
||||
break;
|
||||
/* Fall-through to default from ':' */
|
||||
case ':':
|
||||
case '?':
|
||||
default: throw(NEEDARG_FAIL, mastrcat(argv[0], "[-c|-m] [-lw] [file ...]"));
|
||||
default: throw(NEEDARG_FAIL, mastrcat(argv[0], " [-c|-m] [-lw] [file ...]"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
i = optind;
|
||||
|
||||
|
||||
|
||||
/* for every file we're given... */
|
||||
for(fd = 0, i = optind; i < argc; fclose(fd), i++)
|
||||
/* do-while allows easy opening of stdin */
|
||||
do
|
||||
{
|
||||
/* ...open our file... */
|
||||
if( !(fd = fopen(argv[i], "r")))
|
||||
{
|
||||
printf("%d %d\n", i, optind);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* ...then read until EOF... */
|
||||
for(c = 0; (c = fgetc(fd)) != EOF;)
|
||||
{
|
||||
/* ...and count the goods as we go. */
|
||||
if(!(isblank(c) || c == '\n'))
|
||||
{
|
||||
if(state == OUTWORD)
|
||||
{
|
||||
count[WORDS]++;
|
||||
}
|
||||
|
||||
state = INWORD;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(c == '\n')
|
||||
{
|
||||
count[LINES]++;
|
||||
}
|
||||
|
||||
state = OUTWORD;
|
||||
}
|
||||
|
||||
count[COB]++;
|
||||
}
|
||||
|
||||
/* ...then print our total and reset. */
|
||||
printf("%d %d %d %s\n", count[LINES], count[WORDS], count[COB], argv[i]);
|
||||
/* open file */
|
||||
fd = file_open(argv[i], "r");
|
||||
|
||||
total[COB] += count[COB];
|
||||
total[WORDS] += count[WORDS];
|
||||
total[LINES] += count[LINES];
|
||||
/* process file */
|
||||
wc(fd, current);
|
||||
|
||||
count[COB] = 0;
|
||||
count[WORDS] = 0;
|
||||
count[LINES] = 0;
|
||||
}
|
||||
/* print results */
|
||||
if(haspar)
|
||||
{
|
||||
printres(current, argv[i], pars);
|
||||
}
|
||||
else
|
||||
{
|
||||
printres(current, argv[i], NULL);
|
||||
}
|
||||
|
||||
/* add results to global count */
|
||||
results[WORDS] += current[WORDS];
|
||||
results[LINES] += current[LINES];
|
||||
results[COB] += current[COB];
|
||||
|
||||
/* reset count and file descriptor */
|
||||
current[WORDS] = 0;
|
||||
current[LINES] = 0;
|
||||
current[COB] = 0;
|
||||
|
||||
|
||||
if((argc-optind) > 1)
|
||||
{
|
||||
printf("%d %d %d total\n", total[LINES], total[WORDS], total[COB]);
|
||||
fclose(fd);
|
||||
}
|
||||
/* this would normally be a pre-increment, but that can be confusing, so we use a more explicit approach here */
|
||||
while((i+=1) < argc);
|
||||
|
||||
|
||||
exit(0);
|
||||
|
|
Loading…
Reference in New Issue