Charles.Forsyth20080116-1340f4bb33e18 years agoHistory
228 lines · 4.0 KB · Brainfuck
RawDownload
implement Gzip; include "sys.m";	sys:	Sys;	print, fprint: import sys; include "draw.m"; include "string.m";	str: String; include "daytime.m";	daytime: Daytime; include "bufio.m";	bufio:	Bufio;	Iobuf: import bufio; include "filter.m";	deflate: Filter; DEFLATEPATH: con "/dis/lib/deflate.dis"; Gzip: module{	init:	fn(ctxt: ref Draw->Context, argv: list of string);}; Arg: adt{	argv:	list of string;	c:	int;	opts:	string; 	init:	fn(argv: list of string): ref Arg;	opt:	fn(arg: self ref Arg): int;	arg:	fn(arg: self ref Arg): string;}; argv0:	con "gzip";stderr:	ref Sys->FD;debug	:= 0;verbose	:= 0;level	:= 0; usage(){	fprint(stderr, "usage: %s [-vD1-9] [file ...]\n", argv0);	raise "fail:usage";} nomod(path: string){	sys->fprint(stderr, "%s: cannot load %s: %r\n", argv0, path);	raise "fail:bad module";} init(nil: ref Draw->Context, argv: list of string){	sys = load Sys Sys->PATH;	stderr = sys->fildes(2);	bufio = load Bufio Bufio->PATH;	if (bufio == nil)		nomod(Bufio->PATH);	str = load String String->PATH;	if (str == nil)		nomod(String->PATH);	daytime = load Daytime Daytime->PATH;	if (daytime == nil)		nomod(Daytime->PATH);	deflate = load Filter DEFLATEPATH;	if(deflate == nil)		nomod(DEFLATEPATH); 	arg := Arg.init(argv);	level = 6;	while(c := arg.opt()){		case c{		'D' =>			debug++;		'v' =>			verbose++;		'1' to  '9' =>			level = c - '0';		* =>			usage();		}	} 	deflate->init(); 	argv = arg.argv; 	ok := 1;	if(len argv == 0){		bin := bufio->fopen(sys->fildes(0), Bufio->OREAD);		bout := bufio->fopen(sys->fildes(1), Bufio->OWRITE);		ok = gzip(nil, daytime->now(), bin, bout, "stdin", "stdout");		bout.close();		bin.close();	}else{		for(; argv != nil; argv = tl argv)			ok &= gzipf(hd argv);	}	exit;} gzipf(file: string): int{	bin := bufio->open(file, Bufio->OREAD);	if(bin == nil){		fprint(stderr, "%s: can't open %s: %r\n", argv0, file);		return 0;	}	(ok, dir) := sys->fstat(bin.fd);	if(ok >= 0)		mtime := dir.mtime;	else		mtime = daytime->now(); 	(nil, ofile) := str->splitr(file, "/");	ofile += ".gz";	bout := bufio->create(ofile, Bufio->OWRITE, 8r666);	if(bout == nil){		fprint(stderr, "%s: can't open %s: %r\n", argv0, ofile);		bin.close();		return 0;	} 	ok = gzip(file, mtime, bin, bout, file, ofile);	bout.close();	bin.close();	if (ok)		sys->remove(file);	else		sys->remove(ofile);			return ok;} gzip(nil: string, nil: int, bin, bout: ref Iobuf, fin, fout: string): int{	param := "h" + string level;	incount := outcount := 0;	if (debug)		param += "dv";	rq := deflate->start(param); 	for (;;) {		pick m := <-rq {		Fill =>			n := bin.read(m.buf, len m.buf);			m.reply <-= n;			if (n == -1) {				sys->fprint(stderr, "%s: error reading %s: %r\n", argv0, fin);				return 0;			}			incount += n;		Result =>			n := len m.buf;			if (bout.write(m.buf, n) != n) {				sys->fprint(stderr, "%s: error writing %s: %r\n", argv0, fout);				m.reply <-= -1;				return 0;			}			m.reply <-= 0;			outcount += n;		Info =>			sys->fprint(stderr, "%s\n", m.msg);		Finished =>			comp := 0.0;			if (incount > 0)				comp = 1.0 - real outcount / real incount;			if (verbose)				sys->fprint(stderr, "%s: %5.2f%%\n", fin, comp * 100.0);			return 1;		Error =>			sys->fprint(stderr, "%s: error compressing %s: %s\n", argv0, fin, m.e);			return 0;		}	}} fatal(msg: string){	fprint(stderr, "%s: %s\n", argv0, msg);	exit;} Arg.init(argv: list of string): ref Arg{	if(argv != nil)		argv = tl argv;	return ref Arg(argv, 0, nil);} Arg.opt(arg: self ref Arg): int{	if(arg.opts != ""){		arg.c = arg.opts[0];		arg.opts = arg.opts[1:];		return arg.c;	}	if(arg.argv == nil)		return arg.c = 0;	arg.opts = hd arg.argv;	if(len arg.opts < 2 || arg.opts[0] != '-')		return arg.c = 0;	arg.argv = tl arg.argv;	if(arg.opts == "--")		return arg.c = 0;	arg.c = arg.opts[1];	arg.opts = arg.opts[2:];	return arg.c;} Arg.arg(arg: self ref Arg): string{	s := arg.opts;	arg.opts = "";	if(s != "")		return s;	if(arg.argv == nil)		return "";	s = hd arg.argv;	arg.argv = tl arg.argv;	return s;}