|  | _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"); |