Charles.Forsyth20060303a828770d19 years agoHistory
260 lines · 5.2 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->Prof;}; ignored(s: string){	sys->fprint(stderr, "mprof: warning: %s ignored\n", s);} exits(e: string){	if(profile != nil)		profile->end();	raise "fail:" + e;} pfatal(s: string){	sys->fprint(stderr, "mprof: %s: %s\n", s, profile->lasterror());	exits("error");} badmodule(p: string){	sys->fprint(stderr, "mprof: cannot load %s: %r\n", p);	exits("bad module");} usage(s: string){	sys->fprint(stderr, "mprof: %s\n", s);	sys->fprint(stderr, "usage: mprof [-bcMflnve] [-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->Prof{	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;	begin := end := 0;	ep := 0;	wm := 0;	mem := 0;	exec, mods: list of string;	while((c := arg->opt()) != 0){		case c {			'b' => begin = 1;			'c' => end = 1;			'M' => v |= profile->MODULE;			'f' => v |= profile->FUNCTION;			'l' => v |= profile->LINE;			'n' => v |= profile->FULLHDR;			'v' => v |= profile->VERBOSE;			'm' =>				if((s := arg->arg()) == nil)					usage("missing module name");				mods = s :: mods;			'e' =>				ep = 1;			'g' =>				wm = 1;			'1' =>				mem |= Profile->MAIN;			'2' =>				mem |= Profile->HEAP;			'3' =>				mem |= Profile->IMAGE;			* => 				usage(sys->sprint("unknown option -%c", c));		}	} 	exec = arg->argv(); 	if(begin && end)		ignored("-e option");	if((begin || end) && v != 0)		ignored("output format");	if(begin && exec != nil)		begin = 0;	if(begin == 0 && exec == nil){		if(mods != nil)			ignored("-m option");		mods = nil;	}	if(end){		if(mods != nil)			ignored("-m option");		if(ep || exec != nil)			ignored("command");		profile->end();		exit;	}		for( ; mods != nil; mods = tl mods)		profile->profile(hd mods); 	if(begin){		if(profile->memstart(mem) < 0)			pfatal("cannot start profiling");		exit;	}	r := 0;	if(exec != nil){		if(ep)			profile->profile(disname(hd exec));		if(profile->memstart(mem) < 0)			pfatal("cannot start profiling");		# r = run(ctxt, hd exec, exec);		wfd := openwait(sys->pctl(0, nil));		ci := chan of int;		spawn execute(ctxt, hd exec, exec, ci);		epid := <- ci;		wait(wfd, epid);	}	if(profile->stop() < 0)		pfatal("cannot stop profiling");	if(exec == nil || r >= 0){		modl := profile->memstats();		if(modl.mods == nil)			pfatal("no profile information");		if(wm){			if(exec == nil){				if(profile->memstart(mem) < 0)					pfatal("cannot restart profiling");			}			else				profile->end();			return modl;		}		if(!(v&(profile->MODULE|profile->FUNCTION|profile->LINE)))			v |= profile->MODULE|profile->LINE;		if(profile->memshow(modl, v) < 0)			pfatal("cannot show profile");		if(exec == nil){			if(profile->memstart(mem) < 0)				pfatal("cannot restart profiling");			exit;		}	}	profile->end();	return (nil, 0, 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;	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(c == nil){			sys->fprint(stderr, "mprof: %s: %s\n", cmd, err);			return;		}	}	c->init(ctxt, argl);} # run(ctxt: ref Draw->Context, cmd : string, argl : list of string): int# {# 	file := cmd;# 	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(c == nil){# 			sys->fprint(stderr, "mprof: %s: %s\n", cmd, err);# 			return -1;# 		}# 	}# 	c->init(ctxt, argl);# 	return 0;# } 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;}