/****************************************************/
/*													*/
/* ps_tree.cl										*/
/*													*/
/*    coded by Akito.Kobayashi 2009.2.3				*/
/*  updated by Akito.Kobayashi 2009.2.27			*/
/*													*/
/****************************************************/
//
define const DEBUG_FLG=0;
define const PID_COL=1;
define const PPID_COL=2;
define const TIME_COL=4;
/*
define const CMD_COL=5;
define const SORT_COL=2;
*/
define const CMD_COL=7;
define const SORT_COL=4;

define array argv 100;
define array procl 1000 3;
define array prmn hash 10;
define array col_len 10;
/********************************/
/*								*/
/********************************/
proc main;
//	options 1;
//local x=0;
	only = 0;
	select_pat = '%';

	for (i=1;i<=%0;i++) do
		if left(%$i,2)=='-h' then
			usage(0);
		end if;
	next;
	if %0 >= 2 then
		if %2 == '-' then
			fp = STDIN;
		else
			fp=fopen(%2);
			if !fp then
				fputline(STDERR,'file[',%2,'] open error.err=',ERROR,ERRMSG);
				return ERROR;
			end if;
		end if;
		for (i=3;i<=%0;i++) do
			$1 = %$i;
			if left($1,2)=='-o' then
				only = 1;
			elseif $1 then
				select_pat = concat('%',$1,'%');
			end if;
		next;
	elseif %0 >= 1 then
		fp = STDIN;
	else
		usage(1);
	end if;

	if fp == STDIN then
		putline('*** Input is STDIN!!');
	end if;

	setarray(col_len,0,8,20,3,5);
	parent_pat = concat('%',%1,'%');
	k=m=0;
  try;
	loop;
	 	line=fgetline(fp);
//		if !like(line,'%Main%','%Edit%') thenl continue;
		if like(line,'%grep%','%coal%') thenl continue;
		if (n=getargs(line,argv))<CMD_COL thenl continue;
		ist = (left(argv[TIME_COL],1) IS 'N') ? CMD_COL : CMD_COL+1;
		nm='';
		for (i=ist,ii=0;i<n;i++,ii++) do
			nm &+= argv[i] &+ ' ';
		next;
		ppid = argv[PPID_COL];
		pid = argv[PID_COL];
		if like(line,parent_pat) && like(line,select_pat) then
			v = strings(' ',8-lenb(pid)) &+ pid &+ ' ' &+ nm;
			if only then
				putline(v);
				continue;
			end if;
			f = 0;
			prmn[pid] = list(v);
			k++;
		elseif only then
			continue;
		else
			v = pid &+ ' ' &+ nm;
			f = 1;
		end if;
		procl[m,0] = ppid;
		procl[m,1] = v;
		procl[m,2] = f;
//print procl[m,0] procl[m,1] procl[m,2];
		m++;
	end loop;
  catch;
//	print ERRMSG;
  finally;
//	print 'finally';
  end try;
	if fp!=STDIN thenl fclose(fp);

	if only thenl return ERROR;
  try;
//print m;
	for (i=0;i<m;i++) do
		ppid = procl[i,0];
		if x = ndef('prmn[ppid]','') then
			prmn[ppid] = cons(x,procl[i,1]);
		end if;
//print i ppid prmn[ppid];
	next;

	loop each x in prmn do
		xv = x.Value;
		if !xv thenl continue;
		putline(strings('-',40));
//print x;
		putline(first(xv));
		w = rest(xv);
		n = countv(w);
//print n w;
		sort(1,w,n,'C',SORT_COL,'N');
		for (i=1;i<=n;i++) do
			putline(edit_line($$i));
		next;
	end loop;

	if m>k && select_pat=='' then
		putline(strings('-',40));
		for (i=0;i<m;i++) do
			if procl[i,2] then
				putline(procl[i,1]);
			end if;
		next;
	end if;
  catch;
	print ERRMSG;
  end try;
	return ERROR;
end proc;

/********************************/
/*								*/
/********************************/
function usage(ret);
	fputline(STDERR,'usage: ps_tree parent_name [{-|ps_file} [select_pattern][-o[nly]][-h]]');
	exit ret;
end func;

/********************************/
/*								*/
/********************************/
function edit_line(line);
	nn=getargs(line,argv);
	nm='';
	loop for (i=0;i<nn;i++);
//logparm 2 0 160;
		v = argv[i];
//logparm 2 0;
		if i < 4;
			if i==1;
				v = v &+ strings(' ',col_len[i]-lenb(v));
			else;
				v = strings(' ',col_len[i]-lenb(v)) &+ v;
			end if;
		end if;
		nm &+= v &+ ' ';
	end loop;
	return nm;
end func;
