Charles.Forsyth20060303a828770d19 years agoHistory
190 lines · 3.7 KB · Brainfuck
RawDownload
implement Prof; include "sys.m";	sys: Sys;include "draw.m";include "arg.m";	arg: Arg;include "profile.m";	profile: Profile;include "sh.m"; stderr: ref Sys->FD; Prof: module {	init: fn(nil: ref Draw->Context, argv: list of string);	init0: fn(nil: ref Draw->Context, argv: list of string): Profile->Coverage;}; exits(e: string){	if(profile != nil)		profile->end();	raise "fail:" + e;} pfatal(s: string){	sys->fprint(stderr, "cprof: %s: %s\n", s, profile->lasterror());	exits("error");} badmodule(p: string){	sys->fprint(stderr, "cprof: cannot load %s: %r\n", p);	exits("bad module");} usage(s: string){	sys->fprint(stderr, "cprof: %s\n", s);	sys->fprint(stderr, "usage: cprof [-fner] [-m modname]... cmd [arg ... ]");	exits("usage");} init(ctxt: ref Draw->Context, argv: list of string){	init0(ctxt, argv);} init0(ctxt: ref Draw->Context, argv: list of string): Profile->Coverage{	sys = load Sys Sys->PATH;	stderr = sys->fildes(2);	arg = load Arg Arg->PATH;	if(arg == nil)		badmodule(Arg->PATH);	arg->init(argv);	profile = load Profile Profile->PATH;	if(profile == nil)		badmodule(Profile->PATH);	if(profile->init() < 0)		pfatal("cannot initialize profile device"); 	v := 0;	ep := 0;	rec := 0;	wm := 0;	exec, mods: list of string;	while((c := arg->opt()) != 0){		case c {			'n' => v |= profile->FULLHDR;			'f' => v |= profile->FREQUENCY;			'm' =>				if((s := arg->arg()) == nil)					usage("missing module/file");				mods = s :: mods;			'e' =>				ep = 1;			'r' =>				rec = 1;			'g' =>				wm = 1;			* => 				usage(sys->sprint("unknown option -%c", c));		}	}	exec = arg->argv();	# if(exec == nil)	#	usage("nothing to execute");	for( ; mods != nil; mods = tl mods)		profile->profile(hd mods);	if(ep && exec != nil)		profile->profile(disname(hd exec));	if(exec != nil){		wfd := openwait(sys->pctl(0, nil));		ci := chan of int;		spawn execute(ctxt, hd exec, exec, ci);		epid := <- ci;		if(profile->cpstart(epid) < 0){			ci <-= 0;			pfatal("cannot start profiling");		}		ci <-= 1;		wait(wfd, epid);		if(profile->stop() < 0)			pfatal("cannot stop profiling");	}	if(exec == nil)		modl := profile->cpfstats(v);	else		modl = profile->cpstats(rec, v);	if(modl.mods == nil)		pfatal("no profile information");	if(wm){		cvr := profile->coverage(modl, v);		profile->end();		return cvr;	}	if(!rec && profile->cpshow(modl, v) < 0)		pfatal("cannot show profile");	profile->end();	return nil;} disname(cmd: string): string{	file := cmd;	if(len file<4 || file[len file-4:]!=".dis")		file += ".dis";	if(exists(file))		return file;	if(file[0]!='/' && file[0:2]!="./")		file = "/dis/"+file;	# if(exists(file))	#	return file;	return file;} execute(ctxt: ref Draw->Context, cmd : string, argl : list of string, ci: chan of int){	ci <-= sys->pctl(Sys->FORKNS|Sys->NEWFD|Sys->NEWPGRP, 0 :: 1 :: 2 :: stderr.fd :: nil);	file := cmd;	err := "";	if(len file<4 || file[len file-4:]!=".dis")		file += ".dis";	c := load Command file;	if(c == nil) {		err = sys->sprint("%r");		if(file[0]!='/' && file[0:2]!="./"){			c = load Command "/dis/"+file;			if(c == nil)				err = sys->sprint("%r");		}	}	if(<- ci){		if(c == nil)			sys->fprint(stderr, "cprof: %s: %s\n", cmd, err);		else			c->init(ctxt, argl);	}} openwait(pid : int) : ref Sys->FD{	w := sys->sprint("#p/%d/wait", pid);	fd := sys->open(w, Sys->OREAD);	if (fd == nil)		pfatal("fd == nil in wait");	return fd;} wait(wfd : ref Sys->FD, wpid : int){	n : int; 	buf := array[Sys->WAITLEN] of byte;	status := "";	for(;;) {		if ((n = sys->read(wfd, buf, len buf)) < 0)			pfatal("bad read in wait");		status = string buf[0:n];		if (int status == wpid)			break;	}} exists(f: string): int{	return sys->open(f, Sys->OREAD) != nil;}