1da2e3ebdSchin /*********************************************************************** 2da2e3ebdSchin * * 3da2e3ebdSchin * This software is part of the ast package * 4*34f9b3eeSRoland Mainz * Copyright (c) 1992-2009 AT&T Intellectual Property * 5da2e3ebdSchin * and is licensed under the * 6da2e3ebdSchin * Common Public License, Version 1.0 * 77c2fbfb3SApril 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[] = 30*34f9b3eeSRoland Mainz "[-?\n@(#)$Id: wc (AT&T Research) 2000-08-11 $\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.]" 53*34f9b3eeSRoland Mainz "[L:longest-line|max-line-length?List the longest line length; the newline," 54*34f9b3eeSRoland Mainz "if any, is not counted in the length.]" 55*34f9b3eeSRoland Mainz "[N!:utf8?For \bUTF-8\b locales \b--noutf8\b disables \bUTF-8\b " 56*34f9b3eeSRoland Mainz "optimzations and relies on the native \bmbtowc\b(3).]" 57da2e3ebdSchin "\n" 58da2e3ebdSchin "\n[file ...]\n" 59da2e3ebdSchin "\n" 60da2e3ebdSchin "[+EXIT STATUS?]{" 61da2e3ebdSchin "[+0?All files processed successfully.]" 62da2e3ebdSchin "[+>0?One or more files failed to open or could not be read.]" 63da2e3ebdSchin "}" 64da2e3ebdSchin "[+SEE ALSO?\bcat\b(1), \bisspace\b(3)]" 65da2e3ebdSchin ; 66da2e3ebdSchin 67da2e3ebdSchin 68da2e3ebdSchin #include <cmd.h> 69da2e3ebdSchin #include <wc.h> 70da2e3ebdSchin #include <ls.h> 71da2e3ebdSchin 72da2e3ebdSchin #define ERRORMAX 125 73da2e3ebdSchin 74da2e3ebdSchin static void printout(register Wc_t *wp, register char *name,register int mode) 75da2e3ebdSchin { 76da2e3ebdSchin if (mode&WC_LINES) 77da2e3ebdSchin sfprintf(sfstdout," %7I*d",sizeof(wp->lines),wp->lines); 78da2e3ebdSchin if (mode&WC_WORDS) 79da2e3ebdSchin sfprintf(sfstdout," %7I*d",sizeof(wp->words),wp->words); 80da2e3ebdSchin if (mode&WC_CHARS) 81da2e3ebdSchin sfprintf(sfstdout," %7I*d",sizeof(wp->chars),wp->chars); 82da2e3ebdSchin if (mode&WC_LONGEST) 83da2e3ebdSchin sfprintf(sfstdout," %7I*d",sizeof(wp->chars),wp->longest); 84da2e3ebdSchin if (name) 85da2e3ebdSchin sfprintf(sfstdout," %s",name); 86da2e3ebdSchin sfputc(sfstdout,'\n'); 87da2e3ebdSchin } 88da2e3ebdSchin 89da2e3ebdSchin int 90da2e3ebdSchin b_wc(int argc,register char **argv, void* context) 91da2e3ebdSchin { 92da2e3ebdSchin register char *cp; 93da2e3ebdSchin register int mode=0, n; 94da2e3ebdSchin register Wc_t *wp; 95da2e3ebdSchin Sfio_t *fp; 96da2e3ebdSchin Sfoff_t tlines=0, twords=0, tchars=0; 97da2e3ebdSchin struct stat statb; 98da2e3ebdSchin 99da2e3ebdSchin cmdinit(argc, argv, context, ERROR_CATALOG, 0); 100*34f9b3eeSRoland Mainz for (;;) 101*34f9b3eeSRoland Mainz { 102*34f9b3eeSRoland Mainz switch (optget(argv, usage)) 103da2e3ebdSchin { 104da2e3ebdSchin case 'c': 105da2e3ebdSchin mode |= WC_CHARS; 106*34f9b3eeSRoland Mainz continue; 107da2e3ebdSchin case 'l': 108da2e3ebdSchin mode |= WC_LINES; 109*34f9b3eeSRoland Mainz continue; 110da2e3ebdSchin case 'L': 111da2e3ebdSchin mode |= WC_LONGEST; 112*34f9b3eeSRoland Mainz continue; 113*34f9b3eeSRoland Mainz case 'N': 114*34f9b3eeSRoland Mainz if (!opt_info.num) 115*34f9b3eeSRoland Mainz mode |= WC_NOUTF8; 116*34f9b3eeSRoland Mainz continue; 117da2e3ebdSchin case 'm': 118da2e3ebdSchin case 'C': 119da2e3ebdSchin mode |= WC_MBYTE; 120*34f9b3eeSRoland Mainz continue; 121da2e3ebdSchin case 'q': 122da2e3ebdSchin mode |= WC_QUIET; 123*34f9b3eeSRoland Mainz continue; 124da2e3ebdSchin case 'w': 125da2e3ebdSchin mode |= WC_WORDS; 126*34f9b3eeSRoland Mainz continue; 127da2e3ebdSchin case ':': 128da2e3ebdSchin error(2, "%s", opt_info.arg); 129da2e3ebdSchin break; 130da2e3ebdSchin case '?': 131da2e3ebdSchin error(ERROR_usage(2), "%s", opt_info.arg); 132da2e3ebdSchin break; 133da2e3ebdSchin } 134*34f9b3eeSRoland Mainz break; 135*34f9b3eeSRoland Mainz } 136da2e3ebdSchin argv += opt_info.index; 137da2e3ebdSchin if (error_info.errors) 138da2e3ebdSchin error(ERROR_usage(2), "%s", optusage(NiL)); 139da2e3ebdSchin if (mode&WC_MBYTE) 140da2e3ebdSchin { 141da2e3ebdSchin if (mode&WC_CHARS) 142da2e3ebdSchin error(2, "-c and -C are mutually exclusive"); 143da2e3ebdSchin if (!mbwide()) 144da2e3ebdSchin mode &= ~WC_MBYTE; 145*34f9b3eeSRoland Mainz mode |= WC_CHARS; 146da2e3ebdSchin } 147da2e3ebdSchin if (!(mode&(WC_WORDS|WC_CHARS|WC_LINES|WC_MBYTE|WC_LONGEST))) 148da2e3ebdSchin mode |= (WC_WORDS|WC_CHARS|WC_LINES); 149da2e3ebdSchin if (!(wp = wc_init(mode))) 150da2e3ebdSchin error(3,"internal error"); 151da2e3ebdSchin if (cp = *argv) 152da2e3ebdSchin argv++; 153*34f9b3eeSRoland Mainz n = 0; 154da2e3ebdSchin do 155da2e3ebdSchin { 156da2e3ebdSchin if (!cp || streq(cp,"-")) 157da2e3ebdSchin fp = sfstdin; 158da2e3ebdSchin else if (!(fp = sfopen(NiL,cp,"r"))) 159da2e3ebdSchin { 160da2e3ebdSchin error(ERROR_system(0),"%s: cannot open",cp); 161da2e3ebdSchin continue; 162da2e3ebdSchin } 163da2e3ebdSchin if (cp) 164da2e3ebdSchin n++; 165da2e3ebdSchin if (!(mode&(WC_WORDS|WC_LINES|WC_MBYTE|WC_LONGEST)) && fstat(sffileno(fp),&statb)>=0 166da2e3ebdSchin && S_ISREG(statb.st_mode)) 167da2e3ebdSchin { 168da2e3ebdSchin wp->chars = statb.st_size - lseek(sffileno(fp),0L,1); 169da2e3ebdSchin lseek(sffileno(fp),0L,2); 170da2e3ebdSchin } 171da2e3ebdSchin else 172da2e3ebdSchin wc_count(wp, fp, cp); 173da2e3ebdSchin if (fp!=sfstdin) 174da2e3ebdSchin sfclose(fp); 175da2e3ebdSchin tchars += wp->chars; 176da2e3ebdSchin twords += wp->words; 177da2e3ebdSchin tlines += wp->lines; 178da2e3ebdSchin printout(wp,cp,mode); 179*34f9b3eeSRoland Mainz } while (cp= *argv++); 180da2e3ebdSchin if (n > 1) 181da2e3ebdSchin { 182da2e3ebdSchin wp->lines = tlines; 183da2e3ebdSchin wp->chars = tchars; 184da2e3ebdSchin wp->words = twords; 185da2e3ebdSchin printout(wp,"total",mode); 186da2e3ebdSchin } 187*34f9b3eeSRoland Mainz return error_info.errors<ERRORMAX?error_info.errors:ERRORMAX; 188da2e3ebdSchin } 189