/****************************************************************/ /* Count the characters, words and lines in a file. */ /* */ /* By David Megginson, 1991 */ /* Released into the public domain. */ /* */ /* Command line options: */ /* -c Count characters */ /* -w Count words */ /* -l Count lines */ /* (count everything by default) */ /* */ /* Makefile options: */ /* -DBUFFER_SIZE=n Read n bytes at a time */ /* -DSKIP_CR Ignore carriage returns */ /****************************************************************/ /* $Id: wc.c,v 1.2 1991/03/05 09:02:30 david Exp david $ */ /* * $Log: wc.c,v $ * Revision 1.2 1991/03/05 09:02:30 david * Changed `static version' to `static char * version' (duh!) * * Revision 1.1 1991/03/05 08:59:46 david * Initial revision * */ static char * version = "$Id: wc.c,v 1.2 1991/03/05 09:02:30 david Exp david $"; #include #include #include #include #include #include /* The string of legal options for getopt */ #define OPTSTRING "clw" /* The size of the read() buffer. Allow the user to define */ /* this in the Makefile if desired. */ #ifndef BUFFER_SIZE #define BUFFER_SIZE 50000L #endif /* Use this buffer to read in the file */ static char buffer[BUFFER_SIZE]; /* Number of files read so far, and running totals */ static int total_files = 0; static long total_characters = 0; static long total_words = 0; static long total_lines = 0; /* Flags controlled by command-line options */ static int all_flag = 1; /* count everything (default) */ static int c_flag = 0; /* count characters */ static int w_flag = 0; /* count words */ static int l_flag = 0; /* count lines */ static int whitespace_flag = 1; /* whitespace seen */ static int nl_flag = 0; /* newline seen */ /* getopt() stuff */ extern int optind; /* Local functions */ static void do_file( const char * filename,int fd ); static void count_buffer( long * c,long * w,long * l,fpos_t length ); static void show_results( long c,long w,long l,const char * filename ); static void show_totals( void ); main( int ac,const char ** av ) { int opt,current,fd; opt = getopt(ac,av,OPTSTRING); while( opt != EOF ) { switch( opt ) { case 'c': all_flag = 0; c_flag = 1; break; case 'l': all_flag = 0; l_flag = 1; break; case 'w': all_flag = 0; w_flag = 1; break; } opt = getopt(ac,av,OPTSTRING); } if( optind == ac ) { do_file(NULL,0); } else for( current = optind; current < ac; current++ ) { if( !strcmp(av[current],"-") ) do_file(av[current],0); else { fd = open(av[current],O_RDONLY); if( fd < 0 ) { perror(av[current]); exit(1); } do_file(av[current],fd); close(fd); } } if( total_files > 1 ) show_totals(); return 0; } /******* Count the words in a single file. Arguments: const char * filename the file name int fd the file descriptor Return value: none *******/ static void do_file( const char * filename,int fd ) { fpos_t total_read; long c=0, w=0, l=0; whitespace_flag = 1; total_files++; do { total_read = read(fd,buffer,BUFFER_SIZE); #if DEBUG printf("Read %ld characters from %s\n",total_read,filename?filename:"stdin"); #endif if( total_read > 0 ) count_buffer(&c,&w,&l,total_read); } while( total_read == BUFFER_SIZE ); /* if the file ended on a word, count that word too */ if( !whitespace_flag ) w++; /* if the last character was not NL, count the last */ /* line */ if( !nl_flag ) l++; show_results(c,w,l,filename); total_characters += c; total_words += w; total_lines += l; } /******* Count the buffer itself. Arguments: long * c characters long * w words long * l lines fpos_t length characters in buffer Return value: none *******/ void count_buffer( long * c,long * w,long * l,fpos_t length ) { fpos_t pos; for( pos = 0; pos < length; pos++ ) { switch( buffer[pos] ) { #ifdef SKIP_CR case '\r': break; #endif case '\n': (*l)++; if( !whitespace_flag ) (*w)++; whitespace_flag = 1; nl_flag = 1; break; case ' ': case '\t': if( !whitespace_flag ) (*w)++; whitespace_flag = 1; break; default: whitespace_flag = 0; break; } /* Always count a character */ (*c)++; } } /******* Show the results for a file. Arguments: long c characters long w words long l lines const char * filename Return value: none *******/ void show_results( long c,long w,long l,const char * filename ) { if( all_flag || l_flag ) printf("%10ld",l); if( all_flag || w_flag ) printf("%10ld",w); if( all_flag || c_flag ) printf("%10ld",c); if( filename ) printf(" %s",filename); printf("\n"); } /******* Show the final total for more than one file. Arguments: none Return value: none *******/ void show_totals() { if( all_flag || l_flag ) printf("%10ld",total_lines); if( all_flag || w_flag ) printf("%10ld",total_words); if( all_flag || c_flag ) printf("%10ld",total_characters); printf(" TOTAL\n"); }