/* wc.c -- program to count and display the number of lines, words and one of bytes or characters in the named files */ /* first version */ #include #include #include #include #include "support.h" /* Parameters */ enum { CM, L, W }; /* States */ enum { OUTWORD, INWORD }; /* Category names for count[] and result[] */ enum { /* character or byte */ COB, LINES, WORDS }; 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(EXIT_SUCCESS); }