mp-utils/src/wc.c

194 lines
3.0 KiB
C

/* wc.c -- program to count and display the number of lines, words and one of bytes or characters in the named files */
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <ctype.h>
#include "support.h"
/* Parameters */
enum
{
W,
L,
CM
};
/* States */
enum {
OUTWORD,
INWORD
};
/* Category names for count[] and result[] */
enum {
/* character or byte */
LINES,
WORDS,
COB
};
int wc(FILE *fd, int *results)
{
char state;
int c;
state = OUTWORD;
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': pars[CM] = 1;
haspar = 1;
break;
case 'm': pars[CM] = -1;
haspar = 1;
break;
case 'l': pars[L] = 1;
haspar = 1;
break;
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 ...]"));
break;
}
}
i = optind;
/* do-while allows easy opening of stdin */
do
{
/* open file */
fd = file_open(argv[i], "r");
/* process file */
wc(fd, current);
/* 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;
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);
}