Update Makefile. Finish wc.

This commit is contained in:
Mid Favila 2022-10-01 18:46:19 -04:00
parent d8bb1fcc3e
commit 8783d7f5fc
3 changed files with 174 additions and 76 deletions

View File

@ -22,7 +22,7 @@ false: true
install: all install: all
install -Dm0755 ${BIN} ${DESTDIR}/${PREFIX}/bin install -Dm0755 ${BIN} ${DESTDIR}/${PREFIX}/bin
clean: all clean:
rm ${BIN} *.o rm ${BIN} *.o
check: check:

View File

@ -88,3 +88,34 @@ char *mastrcat(char *str1, char *str2)
return nbuf; 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);
}

207
src/wc.c
View File

@ -9,35 +9,121 @@
#include "support.h" #include "support.h"
/* Parameters */
enum enum
{ {
C,
M,
L,
W, W,
L,
CM
};
/* States */
enum {
OUTWORD, OUTWORD,
INWORD, INWORD
};
/* Category names for count[] and result[] */
enum {
/* character or byte */ /* character or byte */
COB = 0, LINES,
WORDS = 1, WORDS,
LINES = 2, COB
}; };
int main(int argc, char **argv) int wc(FILE *fd, int *results)
{ {
char state; char state;
int c, i; int c;
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;
state = OUTWORD; 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; fd = 0;
@ -47,79 +133,60 @@ int main(int argc, char **argv)
{ {
switch(c) switch(c)
{ {
case 'c': par[C] = 1; case 'c': pars[CM] = 1;
par[M] = 0; haspar = 1;
break; break;
case 'm': par[M] = 1; case 'm': pars[CM] = -1;
par[C] = 0; haspar = 1;
break; break;
case 'l': par[L] = 1; case 'l': pars[L] = 1;
haspar = 1;
break; break;
case 'w': par[W] = 1; case 'w': pars[W] = 1;
haspar = 1;
break; break;
/* Fall-through to default from ':' */ /* Fall-through to default from ':' */
case ':': case ':':
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; break;
} }
} }
i = optind;
/* do-while allows easy opening of stdin */
do
{
/* open file */
fd = file_open(argv[i], "r");
/* process file */
wc(fd, current);
/* for every file we're given... */ /* print results */
for(fd = 0, i = optind; i < argc; fclose(fd), i++) if(haspar)
{ {
/* ...open our file... */ printres(current, argv[i], pars);
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 else
{ {
if(c == '\n') printres(current, argv[i], NULL);
{
count[LINES]++;
} }
state = OUTWORD; /* add results to global count */
} results[WORDS] += current[WORDS];
results[LINES] += current[LINES];
count[COB]++; results[COB] += current[COB];
}
/* reset count and file descriptor */
/* ...then print our total and reset. */ current[WORDS] = 0;
printf("%d %d %d %s\n", count[LINES], count[WORDS], count[COB], argv[i]); current[LINES] = 0;
current[COB] = 0;
total[COB] += count[COB];
total[WORDS] += count[WORDS]; fclose(fd);
total[LINES] += count[LINES];
count[COB] = 0;
count[WORDS] = 0;
count[LINES] = 0;
}
if((argc-optind) > 1)
{
printf("%d %d %d total\n", total[LINES], total[WORDS], total[COB]);
} }
/* 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); exit(0);