1da2e3ebdSchin /*********************************************************************** 2da2e3ebdSchin * * 3da2e3ebdSchin * This software is part of the ast package * 4*7c2fbfb3SApril Chin * Copyright (c) 1992-2008 AT&T Intellectual Property * 5da2e3ebdSchin * and is licensed under the * 6da2e3ebdSchin * Common Public License, Version 1.0 * 7*7c2fbfb3SApril Chin * by AT&T Intellectual Property * 8da2e3ebdSchin * * 9da2e3ebdSchin * A copy of the License is available at * 10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt * 11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12da2e3ebdSchin * * 13da2e3ebdSchin * Information and Software Systems Research * 14da2e3ebdSchin * AT&T Research * 15da2e3ebdSchin * Florham Park NJ * 16da2e3ebdSchin * * 17da2e3ebdSchin * Glenn Fowler <gsf@research.att.com> * 18da2e3ebdSchin * David Korn <dgk@research.att.com> * 19da2e3ebdSchin * * 20da2e3ebdSchin ***********************************************************************/ 21da2e3ebdSchin #pragma prototyped 22da2e3ebdSchin /* 23da2e3ebdSchin * David Korn 24da2e3ebdSchin * AT&T Bell Laboratories 25da2e3ebdSchin * 26da2e3ebdSchin * count the number of bytes, words, and lines in a file 27da2e3ebdSchin */ 28da2e3ebdSchin 29da2e3ebdSchin static const char usage[] = 30da2e3ebdSchin "[-?\n@(#)$Id: wc (AT&T Research) 2006-08-25 $\n]" 31da2e3ebdSchin USAGE_LICENSE 32da2e3ebdSchin "[+NAME?wc - print the number of bytes, words, and lines in files]" 33da2e3ebdSchin "[+DESCRIPTION?\bwc\b reads one or more input files and, by default, " 34da2e3ebdSchin "for each file writes a line containing the number of newlines, " 35da2e3ebdSchin "\aword\as, and bytes contained in each file followed by the " 36da2e3ebdSchin "file name to standard output in that order. A \aword\a is " 37da2e3ebdSchin "defined to be a non-zero length string delimited by \bisspace\b(3) " 38da2e3ebdSchin "characters.]" 39da2e3ebdSchin "[+?If more than one file is specified, \bwc\b writes a total count " 40da2e3ebdSchin "for all of the named files with \btotal\b written instead " 41da2e3ebdSchin "of the file name.]" 42da2e3ebdSchin "[+?By default, \bwc\b writes all three counts. Options can specified " 43da2e3ebdSchin "so that only certain counts are written. The options \b-c\b " 44da2e3ebdSchin "and \b-m\b are mutually exclusive.]" 45da2e3ebdSchin "[+?If no \afile\a is given, or if the \afile\a is \b-\b, \bwc\b " 46da2e3ebdSchin "reads from standard input and no filename is written to standard " 47da2e3ebdSchin "output. The start of the file is defined as the current offset.]" 48da2e3ebdSchin "[l:lines?List the line counts.]" 49da2e3ebdSchin "[w:words?List the word counts.]" 50da2e3ebdSchin "[c:bytes|chars:chars?List the byte counts.]" 51da2e3ebdSchin "[m|C:multibyte-chars?List the character counts.]" 52da2e3ebdSchin "[q:quiet?Suppress invalid multibyte character warnings.]" 53da2e3ebdSchin "[L:longest-line|max-line-length?List the longest line length.]" 54da2e3ebdSchin "\n" 55da2e3ebdSchin "\n[file ...]\n" 56da2e3ebdSchin "\n" 57da2e3ebdSchin "[+EXIT STATUS?]{" 58da2e3ebdSchin "[+0?All files processed successfully.]" 59da2e3ebdSchin "[+>0?One or more files failed to open or could not be read.]" 60da2e3ebdSchin "}" 61da2e3ebdSchin "[+SEE ALSO?\bcat\b(1), \bisspace\b(3)]" 62da2e3ebdSchin ; 63da2e3ebdSchin 64da2e3ebdSchin 65da2e3ebdSchin #include <cmd.h> 66da2e3ebdSchin #include <wc.h> 67da2e3ebdSchin #include <ls.h> 68da2e3ebdSchin 69da2e3ebdSchin #define ERRORMAX 125 70da2e3ebdSchin 71da2e3ebdSchin static void printout(register Wc_t *wp, register char *name,register int mode) 72da2e3ebdSchin { 73da2e3ebdSchin if(mode&WC_LINES) 74da2e3ebdSchin sfprintf(sfstdout," %7I*d",sizeof(wp->lines),wp->lines); 75da2e3ebdSchin if(mode&WC_WORDS) 76da2e3ebdSchin sfprintf(sfstdout," %7I*d",sizeof(wp->words),wp->words); 77da2e3ebdSchin if(mode&WC_CHARS) 78da2e3ebdSchin sfprintf(sfstdout," %7I*d",sizeof(wp->chars),wp->chars); 79da2e3ebdSchin if(mode&WC_LONGEST) 80da2e3ebdSchin sfprintf(sfstdout," %7I*d",sizeof(wp->chars),wp->longest); 81da2e3ebdSchin if(name) 82da2e3ebdSchin sfprintf(sfstdout," %s",name); 83da2e3ebdSchin sfputc(sfstdout,'\n'); 84da2e3ebdSchin } 85da2e3ebdSchin 86da2e3ebdSchin int 87da2e3ebdSchin b_wc(int argc,register char **argv, void* context) 88da2e3ebdSchin { 89da2e3ebdSchin register char *cp; 90da2e3ebdSchin register int mode=0, n; 91da2e3ebdSchin register Wc_t *wp; 92da2e3ebdSchin Sfio_t *fp; 93da2e3ebdSchin Sfoff_t tlines=0, twords=0, tchars=0; 94da2e3ebdSchin struct stat statb; 95da2e3ebdSchin 96da2e3ebdSchin cmdinit(argc, argv, context, ERROR_CATALOG, 0); 97da2e3ebdSchin while (n = optget(argv,usage)) switch (n) 98da2e3ebdSchin { 99da2e3ebdSchin case 'c': 100da2e3ebdSchin mode |= WC_CHARS; 101da2e3ebdSchin break; 102da2e3ebdSchin case 'l': 103da2e3ebdSchin mode |= WC_LINES; 104da2e3ebdSchin break; 105da2e3ebdSchin case 'L': 106da2e3ebdSchin mode |= WC_LONGEST; 107da2e3ebdSchin break; 108da2e3ebdSchin case 'm': 109da2e3ebdSchin case 'C': 110da2e3ebdSchin mode |= WC_MBYTE; 111da2e3ebdSchin break; 112da2e3ebdSchin case 'q': 113da2e3ebdSchin mode |= WC_QUIET; 114da2e3ebdSchin break; 115da2e3ebdSchin case 'w': 116da2e3ebdSchin mode |= WC_WORDS; 117da2e3ebdSchin break; 118da2e3ebdSchin case ':': 119da2e3ebdSchin error(2, "%s", opt_info.arg); 120da2e3ebdSchin break; 121da2e3ebdSchin case '?': 122da2e3ebdSchin error(ERROR_usage(2), "%s", opt_info.arg); 123da2e3ebdSchin break; 124da2e3ebdSchin } 125da2e3ebdSchin argv += opt_info.index; 126da2e3ebdSchin if (error_info.errors) 127da2e3ebdSchin error(ERROR_usage(2), "%s", optusage(NiL)); 128da2e3ebdSchin if(mode&WC_MBYTE) 129da2e3ebdSchin { 130da2e3ebdSchin if(mode&WC_CHARS) 131da2e3ebdSchin error(2, "-c and -C are mutually exclusive"); 132da2e3ebdSchin mode |= WC_CHARS; 133da2e3ebdSchin if(!mbwide()) 134da2e3ebdSchin { 135da2e3ebdSchin mode &= ~WC_MBYTE; 136da2e3ebdSchin setlocale(LC_CTYPE, "C"); 137da2e3ebdSchin } 138da2e3ebdSchin } 139da2e3ebdSchin if(!(mode&(WC_WORDS|WC_CHARS|WC_LINES|WC_MBYTE|WC_LONGEST))) 140da2e3ebdSchin mode |= (WC_WORDS|WC_CHARS|WC_LINES); 141da2e3ebdSchin if(!(wp = wc_init(mode))) 142da2e3ebdSchin error(3,"internal error"); 143da2e3ebdSchin if(!(mode&WC_WORDS)) 144da2e3ebdSchin { 145da2e3ebdSchin memzero(wp->space, (1<<CHAR_BIT)); 146da2e3ebdSchin wp->space['\n'] = -1; 147da2e3ebdSchin } 148da2e3ebdSchin if(cp = *argv) 149da2e3ebdSchin argv++; 150da2e3ebdSchin do 151da2e3ebdSchin { 152da2e3ebdSchin if(!cp || streq(cp,"-")) 153da2e3ebdSchin fp = sfstdin; 154da2e3ebdSchin else if(!(fp = sfopen(NiL,cp,"r"))) 155da2e3ebdSchin { 156da2e3ebdSchin error(ERROR_system(0),"%s: cannot open",cp); 157da2e3ebdSchin continue; 158da2e3ebdSchin } 159da2e3ebdSchin if(cp) 160da2e3ebdSchin n++; 161da2e3ebdSchin if(!(mode&(WC_WORDS|WC_LINES|WC_MBYTE|WC_LONGEST)) && fstat(sffileno(fp),&statb)>=0 162da2e3ebdSchin && S_ISREG(statb.st_mode)) 163da2e3ebdSchin { 164da2e3ebdSchin wp->chars = statb.st_size - lseek(sffileno(fp),0L,1); 165da2e3ebdSchin lseek(sffileno(fp),0L,2); 166da2e3ebdSchin } 167da2e3ebdSchin else 168da2e3ebdSchin wc_count(wp, fp, cp); 169da2e3ebdSchin if(fp!=sfstdin) 170da2e3ebdSchin sfclose(fp); 171da2e3ebdSchin tchars += wp->chars; 172da2e3ebdSchin twords += wp->words; 173da2e3ebdSchin tlines += wp->lines; 174da2e3ebdSchin printout(wp,cp,mode); 175da2e3ebdSchin } 176da2e3ebdSchin while(cp= *argv++); 177da2e3ebdSchin if(n>1) 178da2e3ebdSchin { 179da2e3ebdSchin wp->lines = tlines; 180da2e3ebdSchin wp->chars = tchars; 181da2e3ebdSchin wp->words = twords; 182da2e3ebdSchin printout(wp,"total",mode); 183da2e3ebdSchin } 184da2e3ebdSchin return(error_info.errors<ERRORMAX?error_info.errors:ERRORMAX); 185da2e3ebdSchin } 186da2e3ebdSchin 187