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