Charles.Forsyth20060303a828770d19 years agoHistory
303 lines · 11.7 KB · Brainfuck
RawDownload
implement Wc; ## wc -- count things in utf-encoded text files# Bugs:#	The only white space characters recognized are ' ', '\t' and '\n', even though#	ISO 10646 has many more blanks scattered through it.#	Should count characters that cannot occur in any rune (hex f0-ff) separately.#	Should count non-canonical runes (e.g. hex c1,80 instead of hex 40).# include "sys.m";	sys: Sys; include "draw.m"; Wc: module{	init:	fn(ctxt: ref Draw->Context, args: list of string);}; NBUF:	con 8*1024; stderr:	ref Sys->FD;nline, tnline, pline: int;nword, tnword, pword: int;nchar, tnchar, pchar: int;nbadr, tnbadr, pbadr: int;nbyte, tnbyte, pbyte: int; init(nil: ref Draw->Context, argv: list of string){	sys = load Sys Sys->PATH;	stderr = sys->fildes(2); 	for(argv = tl argv; argv != nil; argv = tl argv){		arg := hd argv;		if(len arg < 2 || arg[0] != '-' || arg[1] == '-')			break;		for(i := 1; i < len arg; i++){			case arg[i]{			'l' => pline++;			'w' => pword++;			'c' => pchar++;			'e' => pbadr++;			'b' => pbyte++;			* =>				sys->fprint(stderr, "usage: wc [-lwcbe] [file ...]\n");				raise "fail:usage";			}		}	}	if(pline+pword+pchar+pbadr+pbyte == 0)		pline = pword = pchar = 1;	argc := len argv;	if(argc == 0)		count(sys->fildes(0), "");	else{		for(; argv != nil; argv = tl argv){			name := hd argv;			f := sys->open(name, sys->OREAD);			if(f == nil)				sys->fprint(stderr, "wc: can't open %s: %r\n", name);			else{				count(f, name);				tnline += nline;				tnword += nword;				tnchar += nchar;				tnbadr += nbadr;				tnbyte += nbyte;				f = nil;			}		}		if(argc > 1)			report(tnline, tnword, tnchar, tnbadr, tnbyte, "total");	}	exit;}report(nline, nword, nchar, nbadr, nbyte: int, fname: string){	line := "";	if(pline)		line += sys->sprint(" %7d", nline);	if(pword)		line += sys->sprint(" %7d", nword);	if(pchar)		line += sys->sprint(" %7d", nchar);	if(pbadr)		line += sys->sprint(" %7d", nbadr);	if(pbyte)		line += sys->sprint(" %7d", nbyte);	if(fname != nil)		line += sys->sprint(" %s", fname);	sys->print("%s\n", line[1:]);}## How it works.  Start in statesp.  Each time we read a character,# increment various counts, and do state transitions according to the# following table.  If we're not in statesp or statewd when done, the# file ends with a partial rune.#        |                character#  state |09,20| 0a  |00-7f|80-bf|c0-df|e0-ef|f0-ff# -------+-----+-----+-----+-----+-----+-----+-----# statesp|ASP  |ASPN |AWDW |AWDWX|AC2W |AC3W |AWDWX# statewd|ASP  |ASPN |AWD  |AWDX |AC2  |AC3  |AWDX# statec2|ASPX |ASPNX|AWDX |AWDR |AC2X |AC3X |AWDX# statec3|ASPX |ASPNX|AWDX |AC2R |AC2X |AC3X |AWDX#			# actions	AC2,		# enter statec2	AC2R,		# enter statec2, don't count a rune	AC2W,		# enter statec2, count a word	AC2X,		# enter statec2, count a bad rune	AC3,		# enter statec3	AC3W,		# enter statec3, count a word	AC3X,		# enter statec3, count a bad rune	ASP,		# enter statesp	ASPN,		# enter statesp, count a newline	ASPNX,		# enter statesp, count a newline, count a bad rune	ASPX,		# enter statesp, count a bad rune	AWD,		# enter statewd	AWDR,		# enter statewd, don't count a rune	AWDW,		# enter statewd, count a word	AWDWX,		# enter statewd, count a word, count a bad rune	AWDX:		# enter statewd, count a bad rune		con byte iota; statesp := array[256] of{	# looking for the start of a wordAWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW,	# 00-07AWDW, ASP,  ASPN, AWDW, AWDW, AWDW, AWDW, AWDW,	# 08-0fAWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW,	# 10-17AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW,	# 18-1fASP,  AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW,	# 20-27AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW,	# 28-2fAWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW,	# 30-37AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW,	# 38-3fAWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW,	# 40-47AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW,	# 48-4fAWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW,	# 50-57AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW,	# 58-5fAWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW,	# 60-67AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW,	# 68-6fAWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW,	# 70-77AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW,	# 78-7fAWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,# 80-87AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,# 88-8fAWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,# 90-97AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,# 98-9fAWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,# a0-a7AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,# a8-afAWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,# b0-b7AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,# b8-bfAC2W, AC2W, AC2W, AC2W, AC2W, AC2W, AC2W, AC2W,	# c0-c7AC2W, AC2W, AC2W, AC2W, AC2W, AC2W, AC2W, AC2W,	# c8-cfAC2W, AC2W, AC2W, AC2W, AC2W, AC2W, AC2W, AC2W,	# d0-d7AC2W, AC2W, AC2W, AC2W, AC2W, AC2W, AC2W, AC2W,	# d8-dfAC3W, AC3W, AC3W, AC3W, AC3W, AC3W, AC3W, AC3W,	# e0-e7AC3W, AC3W, AC3W, AC3W, AC3W, AC3W, AC3W, AC3W,	# e8-efAWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,# f0-f7AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,# f8-ff};statewd := array[256] of {	# looking for the next character in a wordAWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,	# 00-07AWD,  ASP,  ASPN, AWD,  AWD,  AWD,  AWD,  AWD,	# 08-0fAWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,	# 10-17AWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,	# 18-1fASP,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,	# 20-27AWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,	# 28-2fAWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,	# 30-37AWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,	# 38-3fAWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,	# 40-47AWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,	# 48-4fAWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,	# 50-57AWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,	# 58-5fAWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,	# 60-67AWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,	# 68-6fAWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,	# 70-77AWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,  AWD,	# 78-7fAWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 80-87AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 88-8fAWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 90-97AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 98-9fAWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# a0-a7AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# a8-afAWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# b0-b7AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# b8-bfAC2,  AC2,  AC2,  AC2,  AC2,  AC2,  AC2,  AC2,	# c0-c7AC2,  AC2,  AC2,  AC2,  AC2,  AC2,  AC2,  AC2,	# c8-cfAC2,  AC2,  AC2,  AC2,  AC2,  AC2,  AC2,  AC2,	# d0-d7AC2,  AC2,  AC2,  AC2,  AC2,  AC2,  AC2,  AC2,	# d8-dfAC3,  AC3,  AC3,  AC3,  AC3,  AC3,  AC3,  AC3,	# e0-e7AC3,  AC3,  AC3,  AC3,  AC3,  AC3,  AC3,  AC3,	# e8-efAWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# f0-f7AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# f8-ff};statec2 := array[256] of {	# looking for 10xxxxxx to complete a runeAWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 00-07AWDX, ASPX, ASPNX,AWDX, AWDX, AWDX, AWDX, AWDX,	# 08-0fAWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 10-17AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 18-1fASPX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 20-27AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 28-2fAWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 30-37AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 38-3fAWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 40-47AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 48-4fAWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 50-57AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 58-5fAWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 60-67AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 68-6fAWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 70-77AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 78-7fAWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR,	# 80-87AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR,	# 88-8fAWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR,	# 90-97AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR,	# 98-9fAWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR,	# a0-a7AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR,	# a8-afAWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR,	# b0-b7AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR,	# b8-bfAC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X,	# c0-c7AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X,	# c8-cfAC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X,	# d0-d7AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X,	# d8-dfAC3X, AC3X, AC3X, AC3X, AC3X, AC3X, AC3X, AC3X,	# e0-e7AC3X, AC3X, AC3X, AC3X, AC3X, AC3X, AC3X, AC3X,	# e8-efAWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# f0-f7AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# f8-ff};statec3 := array[256] of {	# looking for 10xxxxxx,10xxxxxx to complete a runeAWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 00-07AWDX, ASPX, ASPNX,AWDX, AWDX, AWDX, AWDX, AWDX,	# 08-0fAWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 10-17AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 18-1fASPX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 20-27AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 28-2fAWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 30-37AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 38-3fAWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 40-47AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 48-4fAWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 50-57AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 58-5fAWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 60-67AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 68-6fAWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 70-77AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# 78-7fAC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R,	# 80-87AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R,	# 88-8fAC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R,	# 90-97AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R,	# 98-9fAC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R,	# a0-a7AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R,	# a8-afAC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R,	# b0-b7AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R,	# b8-bfAC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X,	# c0-c7AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X,	# c8-cfAC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X,	# d0-d7AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X,	# d8-dfAC3X, AC3X, AC3X, AC3X, AC3X, AC3X, AC3X, AC3X,	# e0-e7AC3X, AC3X, AC3X, AC3X, AC3X, AC3X, AC3X, AC3X,	# e8-efAWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# f0-f7AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX,	# f8-ff};buf := array[NBUF] of byte;count(f: ref Sys->FD, name: string){	state := statesp;	nline = nword = nchar = nbadr = nbyte = 0;	n := 0;	for(;;){		n = sys->read(f, buf, NBUF);		if(n <= 0)			break;		nbyte += n;		nchar += n;	# might be too large, gets decreased later		i := 0;		do{			case int state[int buf[i++]]{			int AC2 =>   state = statec2;			int AC2R =>  state = statec2; nchar--;			int AC2W =>  state = statec2; nword++;			int AC2X =>  state = statec2;          nbadr++;			int AC3 =>   state = statec3;			int AC3W =>  state = statec3; nword++;			int AC3X =>  state = statec3;          nbadr++;			int ASP =>   state = statesp;			int ASPN =>  state = statesp; nline++;			int ASPNX => state = statesp; nline++; nbadr++;			int ASPX =>  state = statesp;          nbadr++;			int AWD =>   state = statewd;			int AWDR =>  state = statewd; nchar--;			int AWDW =>  state = statewd; nword++;			int AWDWX => state = statewd; nword++; nbadr++;			int AWDX =>  state = statewd;          nbadr++;			}		}while(i < n);	}	if(state!=statesp && state!=statewd)		nbadr++;	if(n < 0)		sys->fprint(stderr, "wc: error reading %s: %r\n", name);	report(nline, nword, nchar, nbadr, nbyte, name);}