| _ni=0;	// network indent level | 
 |  | 
 | defn | 
 | _ni() { | 
 | 	loop 1,_ni do { | 
 | 		print("\t"); | 
 | 	} | 
 | } | 
 |  | 
 | defn | 
 | ipdev(n) { | 
 | 	_ipfs(*(ipfs+4*n)); | 
 | } | 
 |  | 
 | // the funny _foo/foo pairs exist so that if we get | 
 | // interrupted in the middle of one of these, _ni will  | 
 | // get reset to 0 next time an external call happens. | 
 |  | 
 | defn | 
 | _ipfs(fs) { | 
 | 	complex Fs fs; | 
 | 	local i; | 
 |  | 
 | 	print("ipfs(", fs\X, ")  #I", fs.dev\D, "\n"); | 
 | 	i=0; | 
 | 	_ni = _ni+1; | 
 | 	while i < fs.np do { | 
 | 		_proto(*(fs.p+i*4)); | 
 | 		i = i + 1; | 
 | 	} | 
 | 	_ni = _ni-1; | 
 | } | 
 |  | 
 | defn | 
 | ipfs(fs) { | 
 | 	_ni = 0; | 
 | 	_ipfs(fs); | 
 | } | 
 |  | 
 | defn | 
 | _proto(p) { | 
 | 	local c; | 
 | 	complex Proto p; | 
 | 	_ni(); | 
 | 	print("proto(", p\X, ") ", *(p.name\s), "\n"); | 
 | 	_ni = _ni+1; | 
 | 	local i; | 
 | 	i = 0; | 
 | 	while i < p.nc do { | 
 | 		c = *(p.conv+i*4); | 
 | 		complex Conv c; | 
 | 		if c != 0 && c.inuse then  | 
 | 			_conv(*(p.conv+i*4)); | 
 | 		i = i + 1; | 
 | 	} | 
 | 	_ni = _ni - 1; | 
 | } | 
 |  | 
 | defn | 
 | proto(p) { | 
 | 	_ni = 0; | 
 | 	_proto(p); | 
 | } | 
 |  | 
 | defn | 
 | _conv(c) { | 
 | 	complex Conv c; | 
 | 	_ni(); | 
 | 	local p; | 
 | 	p = c.p; | 
 | 	complex Proto p; | 
 | 	print("conv(", c\X, ") ", *(p.name\s), "/", c.x\D, " ",  | 
 | 		iptostr(*(c.laddr+12)), "!", c.lport\D, " ", iptostr(*(c.raddr+12)),  | 
 | 		"!", c.rport\D, " rq ", qtostr(c.rq), " wq ", qtostr(c.wq),  | 
 | 		" eq ", qtostr(c.eq), "\n"); | 
 | } | 
 |  | 
 | defn | 
 | conv(c) { | 
 | 	_ni = 0; | 
 | 	_conv(c); | 
 | } | 
 |  | 
 | defn | 
 | iptostr(a) | 
 | { | 
 | 	// BUG: little endian | 
 | 	return itoa(a&0xFF)+"."+itoa((a>>8)&0xFF)+"."+itoa((a>>16)&0xFF)+"."+itoa((a>>24)&0xFF); | 
 | } | 
 |  | 
 | defn | 
 | qtostr(q) | 
 | { | 
 | 	complex Queue q; | 
 |  | 
 | 	return "queue("+itoa(q, "%lux")+") ["+itoa(q.len, "%d")+","+itoa(q.dlen, "%d")+","+itoa(qblocks(q), "%d")+"]"; | 
 | } | 
 |  | 
 | defn | 
 | qblocks(q) | 
 | { | 
 | 	complex Queue q; | 
 | 	local b, n; | 
 |  | 
 | 	b = q.bfirst; | 
 | 	n = 0; | 
 | 	while b != 0 do {  | 
 | 		n = n + 1; | 
 | 		complex Block b; | 
 | 		b = b.next; | 
 | 	} | 
 | 	return n; | 
 | } | 
 |  | 
 | defn | 
 | _queue(q) | 
 | { | 
 | 	complex Queue q; | 
 | 	local b; | 
 |  | 
 | 	print("queue(", q\X, ") len ", q.len\D, " dlen ", q.dlen\D, " limit ", q.limit\D, " nblocks ", qblocks(q)\D); | 
 | 	if q.state & Qstarve then  | 
 | 		print(" starve"); | 
 | 	if q.state & Qmsg then | 
 | 		print(" msg"); | 
 | 	if q.state & Qclosed then | 
 | 		print(" closed"); | 
 | 	if q.state & Qflow then | 
 | 		print(" flow"); | 
 | 	if q.state & Qcoalesce then | 
 | 		print(" coalesce"); | 
 | 	print("\n"); | 
 |  | 
 | 	b = q.bfirst; | 
 | 	_ni = _ni+1; | 
 | 	while b != 0 do { | 
 | 		_block(b); | 
 | 		complex Block b; | 
 | 		b = b.next; | 
 | 	} | 
 | 	_ni = _ni - 1; | 
 | } | 
 |  | 
 | defn | 
 | queue(q) | 
 | { | 
 | 	_ni = 0; | 
 | 	_queue(q); | 
 | } | 
 |  | 
 | defn | 
 | _block(b) | 
 | { | 
 | 	complex Block b; | 
 |  | 
 | 	_ni(); | 
 | 	print("block(", b\X, ") base ", b.base\X, " rp ", b.rp\X, "/", b.rp-b.base\D, " wp ", b.wp\X, "/", b.wp-b.base\D, " lim ", b.lim\X, "/", b.lim-b.base\D, "\n"); | 
 | } | 
 |  | 
 | defn | 
 | block(b) | 
 | { | 
 | 	_ni = 0; | 
 | 	block(b); | 
 | } | 
 |  | 
 | print(acidfile); | 
 | needacid("tcp"); | 
 | needacid("qio"); |