15e96a66cSDavid du Colombier #include "stdinc.h"
25e96a66cSDavid du Colombier #include "dat.h"
35e96a66cSDavid du Colombier #include "fns.h"
45e96a66cSDavid du Colombier #include <draw.h>
55e96a66cSDavid du Colombier #include <event.h>
65e96a66cSDavid du Colombier
75e96a66cSDavid du Colombier /* --- tree.h */
85e96a66cSDavid du Colombier typedef struct Tree Tree;
95e96a66cSDavid du Colombier typedef struct Tnode Tnode;
105e96a66cSDavid du Colombier
115e96a66cSDavid du Colombier struct Tree
125e96a66cSDavid du Colombier {
135e96a66cSDavid du Colombier Tnode *root;
145e96a66cSDavid du Colombier Point offset;
155e96a66cSDavid du Colombier Image *clipr;
165e96a66cSDavid du Colombier };
175e96a66cSDavid du Colombier
185e96a66cSDavid du Colombier struct Tnode
195e96a66cSDavid du Colombier {
205e96a66cSDavid du Colombier Point offset;
215e96a66cSDavid du Colombier
225e96a66cSDavid du Colombier char *str;
235e96a66cSDavid du Colombier // char *(*strfn)(Tnode*);
245e96a66cSDavid du Colombier // uint (*draw)(Tnode*, Image*, Image*, Point);
255e96a66cSDavid du Colombier void (*expand)(Tnode*);
265e96a66cSDavid du Colombier void (*collapse)(Tnode*);
275e96a66cSDavid du Colombier
285e96a66cSDavid du Colombier uint expanded;
295e96a66cSDavid du Colombier Tnode **kid;
305e96a66cSDavid du Colombier int nkid;
315e96a66cSDavid du Colombier void *aux;
325e96a66cSDavid du Colombier };
335e96a66cSDavid du Colombier
345e96a66cSDavid du Colombier typedef struct Atree Atree;
355e96a66cSDavid du Colombier struct Atree
365e96a66cSDavid du Colombier {
375e96a66cSDavid du Colombier int resizefd;
385e96a66cSDavid du Colombier Tnode *root;
395e96a66cSDavid du Colombier };
405e96a66cSDavid du Colombier
415e96a66cSDavid du Colombier Atree *atreeinit(char*);
425e96a66cSDavid du Colombier
435e96a66cSDavid du Colombier /* --- visfossil.c */
445e96a66cSDavid du Colombier Tnode *initxheader(void);
455e96a66cSDavid du Colombier Tnode *initxcache(char *name);
465e96a66cSDavid du Colombier Tnode *initxsuper(void);
475e96a66cSDavid du Colombier Tnode *initxlocalroot(char *name, u32int addr);
485e96a66cSDavid du Colombier Tnode *initxentry(Entry);
495e96a66cSDavid du Colombier Tnode *initxsource(Entry, int);
505e96a66cSDavid du Colombier Tnode *initxentryblock(Block*, Entry*);
515e96a66cSDavid du Colombier Tnode *initxdatablock(Block*, uint);
525e96a66cSDavid du Colombier Tnode *initxroot(char *name, uchar[VtScoreSize]);
535e96a66cSDavid du Colombier
545e96a66cSDavid du Colombier int fd;
555e96a66cSDavid du Colombier Header h;
565e96a66cSDavid du Colombier Super super;
575e96a66cSDavid du Colombier VtSession *z;
585e96a66cSDavid du Colombier VtRoot vac;
595e96a66cSDavid du Colombier int showinactive;
605e96a66cSDavid du Colombier
615e96a66cSDavid du Colombier /*
625e96a66cSDavid du Colombier * dumbed down versions of fossil routines
635e96a66cSDavid du Colombier */
645e96a66cSDavid du Colombier char*
bsStr(int state)655e96a66cSDavid du Colombier bsStr(int state)
665e96a66cSDavid du Colombier {
675e96a66cSDavid du Colombier static char s[100];
685e96a66cSDavid du Colombier
695e96a66cSDavid du Colombier if(state == BsFree)
705e96a66cSDavid du Colombier return "Free";
715e96a66cSDavid du Colombier if(state == BsBad)
725e96a66cSDavid du Colombier return "Bad";
735e96a66cSDavid du Colombier
745e96a66cSDavid du Colombier sprint(s, "%x", state);
755e96a66cSDavid du Colombier if(!(state&BsAlloc))
765e96a66cSDavid du Colombier strcat(s, ",Free"); /* should not happen */
775e96a66cSDavid du Colombier if(state&BsVenti)
785e96a66cSDavid du Colombier strcat(s, ",Venti");
795e96a66cSDavid du Colombier if(state&BsClosed)
805e96a66cSDavid du Colombier strcat(s, ",Closed");
815e96a66cSDavid du Colombier return s;
825e96a66cSDavid du Colombier }
835e96a66cSDavid du Colombier
845e96a66cSDavid du Colombier char *bttab[] = {
855e96a66cSDavid du Colombier "BtData",
865e96a66cSDavid du Colombier "BtData+1",
875e96a66cSDavid du Colombier "BtData+2",
885e96a66cSDavid du Colombier "BtData+3",
895e96a66cSDavid du Colombier "BtData+4",
905e96a66cSDavid du Colombier "BtData+5",
915e96a66cSDavid du Colombier "BtData+6",
925e96a66cSDavid du Colombier "BtData+7",
935e96a66cSDavid du Colombier "BtDir",
945e96a66cSDavid du Colombier "BtDir+1",
955e96a66cSDavid du Colombier "BtDir+2",
965e96a66cSDavid du Colombier "BtDir+3",
975e96a66cSDavid du Colombier "BtDir+4",
985e96a66cSDavid du Colombier "BtDir+5",
995e96a66cSDavid du Colombier "BtDir+6",
1005e96a66cSDavid du Colombier "BtDir+7",
1015e96a66cSDavid du Colombier };
1025e96a66cSDavid du Colombier
1035e96a66cSDavid du Colombier char*
btStr(int type)1045e96a66cSDavid du Colombier btStr(int type)
1055e96a66cSDavid du Colombier {
1065e96a66cSDavid du Colombier if(type < nelem(bttab))
1075e96a66cSDavid du Colombier return bttab[type];
1085e96a66cSDavid du Colombier return "unknown";
1095e96a66cSDavid du Colombier }
1105e96a66cSDavid du Colombier #pragma varargck argpos stringnode 1
1115e96a66cSDavid du Colombier
1125e96a66cSDavid du Colombier Block*
allocBlock(void)1135e96a66cSDavid du Colombier allocBlock(void)
1145e96a66cSDavid du Colombier {
1155e96a66cSDavid du Colombier Block *b;
1165e96a66cSDavid du Colombier
1175e96a66cSDavid du Colombier b = mallocz(sizeof(Block)+h.blockSize, 1);
1185e96a66cSDavid du Colombier b->data = (void*)&b[1];
1195e96a66cSDavid du Colombier return b;
1205e96a66cSDavid du Colombier }
1215e96a66cSDavid du Colombier
1225e96a66cSDavid du Colombier void
blockPut(Block * b)1235e96a66cSDavid du Colombier blockPut(Block *b)
1245e96a66cSDavid du Colombier {
1255e96a66cSDavid du Colombier free(b);
1265e96a66cSDavid du Colombier }
1275e96a66cSDavid du Colombier
1285e96a66cSDavid du Colombier static u32int
partStart(int part)1295e96a66cSDavid du Colombier partStart(int part)
1305e96a66cSDavid du Colombier {
1315e96a66cSDavid du Colombier switch(part){
1325e96a66cSDavid du Colombier default:
1335e96a66cSDavid du Colombier assert(0);
1345e96a66cSDavid du Colombier case PartSuper:
1355e96a66cSDavid du Colombier return h.super;
1365e96a66cSDavid du Colombier case PartLabel:
1375e96a66cSDavid du Colombier return h.label;
1385e96a66cSDavid du Colombier case PartData:
1395e96a66cSDavid du Colombier return h.data;
1405e96a66cSDavid du Colombier }
1415e96a66cSDavid du Colombier }
1425e96a66cSDavid du Colombier
1435e96a66cSDavid du Colombier
1445e96a66cSDavid du Colombier static u32int
partEnd(int part)1455e96a66cSDavid du Colombier partEnd(int part)
1465e96a66cSDavid du Colombier {
1475e96a66cSDavid du Colombier switch(part){
1485e96a66cSDavid du Colombier default:
1495e96a66cSDavid du Colombier assert(0);
1505e96a66cSDavid du Colombier case PartSuper:
1515e96a66cSDavid du Colombier return h.super+1;
1525e96a66cSDavid du Colombier case PartLabel:
1535e96a66cSDavid du Colombier return h.data;
1545e96a66cSDavid du Colombier case PartData:
1555e96a66cSDavid du Colombier return h.end;
1565e96a66cSDavid du Colombier }
1575e96a66cSDavid du Colombier }
1585e96a66cSDavid du Colombier
1595e96a66cSDavid du Colombier Block*
readBlock(int part,u32int addr)1605e96a66cSDavid du Colombier readBlock(int part, u32int addr)
1615e96a66cSDavid du Colombier {
1625e96a66cSDavid du Colombier u32int start, end;
1635e96a66cSDavid du Colombier u64int offset;
1645e96a66cSDavid du Colombier int n, nn;
1655e96a66cSDavid du Colombier Block *b;
1665e96a66cSDavid du Colombier uchar *buf;
1675e96a66cSDavid du Colombier
1685e96a66cSDavid du Colombier start = partStart(part);
1695e96a66cSDavid du Colombier end = partEnd(part);
1705e96a66cSDavid du Colombier if(addr >= end-start){
1715e96a66cSDavid du Colombier werrstr("bad addr 0x%.8ux; wanted 0x%.8ux - 0x%.8ux", addr, start, end);
1725e96a66cSDavid du Colombier return nil;
1735e96a66cSDavid du Colombier }
1745e96a66cSDavid du Colombier
1755e96a66cSDavid du Colombier b = allocBlock();
1765e96a66cSDavid du Colombier b->addr = addr;
1775e96a66cSDavid du Colombier buf = b->data;
1785e96a66cSDavid du Colombier offset = ((u64int)(addr+start))*h.blockSize;
1795e96a66cSDavid du Colombier n = h.blockSize;
1805e96a66cSDavid du Colombier while(n > 0){
1815e96a66cSDavid du Colombier nn = pread(fd, buf, n, offset);
1825e96a66cSDavid du Colombier if(nn < 0){
1835e96a66cSDavid du Colombier blockPut(b);
1845e96a66cSDavid du Colombier return nil;
1855e96a66cSDavid du Colombier }
1865e96a66cSDavid du Colombier if(nn == 0){
1875e96a66cSDavid du Colombier werrstr("short read");
1885e96a66cSDavid du Colombier blockPut(b);
1895e96a66cSDavid du Colombier return nil;
1905e96a66cSDavid du Colombier }
1915e96a66cSDavid du Colombier n -= nn;
1925e96a66cSDavid du Colombier offset += nn;
1935e96a66cSDavid du Colombier buf += nn;
1945e96a66cSDavid du Colombier }
1955e96a66cSDavid du Colombier return b;
1965e96a66cSDavid du Colombier }
1975e96a66cSDavid du Colombier
1985e96a66cSDavid du Colombier int vtType[BtMax] = {
1995e96a66cSDavid du Colombier VtDataType, /* BtData | 0 */
2005e96a66cSDavid du Colombier VtPointerType0, /* BtData | 1 */
2015e96a66cSDavid du Colombier VtPointerType1, /* BtData | 2 */
2025e96a66cSDavid du Colombier VtPointerType2, /* BtData | 3 */
2035e96a66cSDavid du Colombier VtPointerType3, /* BtData | 4 */
2045e96a66cSDavid du Colombier VtPointerType4, /* BtData | 5 */
2055e96a66cSDavid du Colombier VtPointerType5, /* BtData | 6 */
2065e96a66cSDavid du Colombier VtPointerType6, /* BtData | 7 */
2075e96a66cSDavid du Colombier VtDirType, /* BtDir | 0 */
2085e96a66cSDavid du Colombier VtPointerType0, /* BtDir | 1 */
2095e96a66cSDavid du Colombier VtPointerType1, /* BtDir | 2 */
2105e96a66cSDavid du Colombier VtPointerType2, /* BtDir | 3 */
2115e96a66cSDavid du Colombier VtPointerType3, /* BtDir | 4 */
2125e96a66cSDavid du Colombier VtPointerType4, /* BtDir | 5 */
2135e96a66cSDavid du Colombier VtPointerType5, /* BtDir | 6 */
2145e96a66cSDavid du Colombier VtPointerType6, /* BtDir | 7 */
2155e96a66cSDavid du Colombier };
2165e96a66cSDavid du Colombier
2175e96a66cSDavid du Colombier Block*
ventiBlock(uchar score[VtScoreSize],uint type)2185e96a66cSDavid du Colombier ventiBlock(uchar score[VtScoreSize], uint type)
2195e96a66cSDavid du Colombier {
2205e96a66cSDavid du Colombier int n;
2215e96a66cSDavid du Colombier Block *b;
2225e96a66cSDavid du Colombier
2235e96a66cSDavid du Colombier b = allocBlock();
2245e96a66cSDavid du Colombier memmove(b->score, score, VtScoreSize);
2255e96a66cSDavid du Colombier b->addr = NilBlock;
2265e96a66cSDavid du Colombier
2275e96a66cSDavid du Colombier n = vtRead(z, b->score, vtType[type], b->data, h.blockSize);
2285e96a66cSDavid du Colombier if(n < 0){
2295e96a66cSDavid du Colombier fprint(2, "vtRead returns %d: %R\n", n);
2305e96a66cSDavid du Colombier blockPut(b);
2315e96a66cSDavid du Colombier return nil;
2325e96a66cSDavid du Colombier }
2335e96a66cSDavid du Colombier vtZeroExtend(vtType[type], b->data, n, h.blockSize);
2345e96a66cSDavid du Colombier b->l.type = type;
2355e96a66cSDavid du Colombier b->l.state = 0;
2365e96a66cSDavid du Colombier b->l.tag = 0;
2375e96a66cSDavid du Colombier b->l.epoch = 0;
2385e96a66cSDavid du Colombier return b;
2395e96a66cSDavid du Colombier }
2405e96a66cSDavid du Colombier
2415e96a66cSDavid du Colombier Block*
dataBlock(uchar score[VtScoreSize],uint type,uint tag)2425e96a66cSDavid du Colombier dataBlock(uchar score[VtScoreSize], uint type, uint tag)
2435e96a66cSDavid du Colombier {
2445e96a66cSDavid du Colombier Block *b, *bl;
2455e96a66cSDavid du Colombier int lpb;
2465e96a66cSDavid du Colombier Label l;
2475e96a66cSDavid du Colombier u32int addr;
2485e96a66cSDavid du Colombier
2495e96a66cSDavid du Colombier addr = globalToLocal(score);
2505e96a66cSDavid du Colombier if(addr == NilBlock)
2515e96a66cSDavid du Colombier return ventiBlock(score, type);
2525e96a66cSDavid du Colombier
2535e96a66cSDavid du Colombier lpb = h.blockSize/LabelSize;
2545e96a66cSDavid du Colombier bl = readBlock(PartLabel, addr/lpb);
2555e96a66cSDavid du Colombier if(bl == nil)
2565e96a66cSDavid du Colombier return nil;
2575e96a66cSDavid du Colombier if(!labelUnpack(&l, bl->data, addr%lpb)){
2585e96a66cSDavid du Colombier werrstr("%R");
2595e96a66cSDavid du Colombier blockPut(bl);
2605e96a66cSDavid du Colombier return nil;
2615e96a66cSDavid du Colombier }
2625e96a66cSDavid du Colombier blockPut(bl);
2635e96a66cSDavid du Colombier if(l.type != type){
2645e96a66cSDavid du Colombier werrstr("type mismatch; got %d (%s) wanted %d (%s)",
2655e96a66cSDavid du Colombier l.type, btStr(l.type), type, btStr(type));
2665e96a66cSDavid du Colombier return nil;
2675e96a66cSDavid du Colombier }
2685e96a66cSDavid du Colombier if(tag && l.tag != tag){
2695e96a66cSDavid du Colombier werrstr("tag mismatch; got 0x%.8ux wanted 0x%.8ux",
2705e96a66cSDavid du Colombier l.tag, tag);
2715e96a66cSDavid du Colombier return nil;
2725e96a66cSDavid du Colombier }
2735e96a66cSDavid du Colombier b = readBlock(PartData, addr);
2745e96a66cSDavid du Colombier if(b == nil)
2755e96a66cSDavid du Colombier return nil;
2765e96a66cSDavid du Colombier b->l = l;
2775e96a66cSDavid du Colombier return b;
2785e96a66cSDavid du Colombier }
2795e96a66cSDavid du Colombier
2805e96a66cSDavid du Colombier Entry*
copyEntry(Entry e)2815e96a66cSDavid du Colombier copyEntry(Entry e)
2825e96a66cSDavid du Colombier {
2835e96a66cSDavid du Colombier Entry *p;
2845e96a66cSDavid du Colombier
2855e96a66cSDavid du Colombier p = mallocz(sizeof *p, 1);
2865e96a66cSDavid du Colombier *p = e;
2875e96a66cSDavid du Colombier return p;
2885e96a66cSDavid du Colombier }
2895e96a66cSDavid du Colombier
2905e96a66cSDavid du Colombier MetaBlock*
copyMetaBlock(MetaBlock mb)2915e96a66cSDavid du Colombier copyMetaBlock(MetaBlock mb)
2925e96a66cSDavid du Colombier {
2935e96a66cSDavid du Colombier MetaBlock *p;
2945e96a66cSDavid du Colombier
2955e96a66cSDavid du Colombier p = mallocz(sizeof mb, 1);
2965e96a66cSDavid du Colombier *p = mb;
2975e96a66cSDavid du Colombier return p;
2985e96a66cSDavid du Colombier }
2995e96a66cSDavid du Colombier
3005e96a66cSDavid du Colombier /*
3015e96a66cSDavid du Colombier * visualizer
3025e96a66cSDavid du Colombier */
3035e96a66cSDavid du Colombier
304*0c6300e7SDavid du Colombier #pragma varargck argpos stringnode 1
305*0c6300e7SDavid du Colombier
3065e96a66cSDavid du Colombier Tnode*
stringnode(char * fmt,...)3075e96a66cSDavid du Colombier stringnode(char *fmt, ...)
3085e96a66cSDavid du Colombier {
3095e96a66cSDavid du Colombier va_list arg;
3105e96a66cSDavid du Colombier Tnode *t;
3115e96a66cSDavid du Colombier
3125e96a66cSDavid du Colombier t = mallocz(sizeof(Tnode), 1);
3135e96a66cSDavid du Colombier va_start(arg, fmt);
3145e96a66cSDavid du Colombier t->str = vsmprint(fmt, arg);
3155e96a66cSDavid du Colombier va_end(arg);
3165e96a66cSDavid du Colombier t->nkid = -1;
3175e96a66cSDavid du Colombier return t;
3185e96a66cSDavid du Colombier }
3195e96a66cSDavid du Colombier
3205e96a66cSDavid du Colombier void
xcacheexpand(Tnode * t)3215e96a66cSDavid du Colombier xcacheexpand(Tnode *t)
3225e96a66cSDavid du Colombier {
3235e96a66cSDavid du Colombier if(t->nkid >= 0)
3245e96a66cSDavid du Colombier return;
3255e96a66cSDavid du Colombier
3265e96a66cSDavid du Colombier t->nkid = 1;
3275e96a66cSDavid du Colombier t->kid = mallocz(sizeof(t->kid[0])*t->nkid, 1);
3285e96a66cSDavid du Colombier t->kid[0] = initxheader();
3295e96a66cSDavid du Colombier }
3305e96a66cSDavid du Colombier
3315e96a66cSDavid du Colombier Tnode*
initxcache(char * name)3325e96a66cSDavid du Colombier initxcache(char *name)
3335e96a66cSDavid du Colombier {
3345e96a66cSDavid du Colombier Tnode *t;
3355e96a66cSDavid du Colombier
3365e96a66cSDavid du Colombier if((fd = open(name, OREAD)) < 0)
3375e96a66cSDavid du Colombier sysfatal("cannot open %s: %r", name);
3385e96a66cSDavid du Colombier
3395e96a66cSDavid du Colombier t = stringnode("%s", name);
3405e96a66cSDavid du Colombier t->expand = xcacheexpand;
3415e96a66cSDavid du Colombier return t;
3425e96a66cSDavid du Colombier }
3435e96a66cSDavid du Colombier
3445e96a66cSDavid du Colombier void
xheaderexpand(Tnode * t)3455e96a66cSDavid du Colombier xheaderexpand(Tnode *t)
3465e96a66cSDavid du Colombier {
3475e96a66cSDavid du Colombier if(t->nkid >= 0)
3485e96a66cSDavid du Colombier return;
3495e96a66cSDavid du Colombier
3505e96a66cSDavid du Colombier t->nkid = 1;
3515e96a66cSDavid du Colombier t->kid = mallocz(sizeof(t->kid[0])*t->nkid, 1);
3525e96a66cSDavid du Colombier t->kid[0] = initxsuper();
3535e96a66cSDavid du Colombier //t->kid[1] = initxlabel(h.label);
3545e96a66cSDavid du Colombier //t->kid[2] = initxdata(h.data);
3555e96a66cSDavid du Colombier }
3565e96a66cSDavid du Colombier
3575e96a66cSDavid du Colombier Tnode*
initxheader(void)3585e96a66cSDavid du Colombier initxheader(void)
3595e96a66cSDavid du Colombier {
3605e96a66cSDavid du Colombier u8int buf[HeaderSize];
3615e96a66cSDavid du Colombier Tnode *t;
3625e96a66cSDavid du Colombier
3635e96a66cSDavid du Colombier if(pread(fd, buf, HeaderSize, HeaderOffset) < HeaderSize)
3645e96a66cSDavid du Colombier return stringnode("error reading header: %r");
3655e96a66cSDavid du Colombier if(!headerUnpack(&h, buf))
3665e96a66cSDavid du Colombier return stringnode("error unpacking header: %R");
3675e96a66cSDavid du Colombier
3685e96a66cSDavid du Colombier t = stringnode("header "
3695e96a66cSDavid du Colombier "version=%#ux (%d) "
3705e96a66cSDavid du Colombier "blockSize=%#ux (%d) "
3715e96a66cSDavid du Colombier "super=%#lux (%ld) "
3725e96a66cSDavid du Colombier "label=%#lux (%ld) "
3735e96a66cSDavid du Colombier "data=%#lux (%ld) "
3745e96a66cSDavid du Colombier "end=%#lux (%ld)",
3755e96a66cSDavid du Colombier h.version, h.version, h.blockSize, h.blockSize,
3765e96a66cSDavid du Colombier h.super, h.super,
3775e96a66cSDavid du Colombier h.label, h.label, h.data, h.data, h.end, h.end);
3785e96a66cSDavid du Colombier t->expand = xheaderexpand;
3795e96a66cSDavid du Colombier return t;
3805e96a66cSDavid du Colombier }
3815e96a66cSDavid du Colombier
3825e96a66cSDavid du Colombier void
xsuperexpand(Tnode * t)3835e96a66cSDavid du Colombier xsuperexpand(Tnode *t)
3845e96a66cSDavid du Colombier {
3855e96a66cSDavid du Colombier if(t->nkid >= 0)
3865e96a66cSDavid du Colombier return;
3875e96a66cSDavid du Colombier
3885e96a66cSDavid du Colombier t->nkid = 1;
3895e96a66cSDavid du Colombier t->kid = mallocz(sizeof(t->kid[0])*t->nkid, 1);
3905e96a66cSDavid du Colombier t->kid[0] = initxlocalroot("active", super.active);
3915e96a66cSDavid du Colombier // t->kid[1] = initxlocalroot("next", super.next);
3925e96a66cSDavid du Colombier // t->kid[2] = initxlocalroot("current", super.current);
3935e96a66cSDavid du Colombier }
3945e96a66cSDavid du Colombier
3955e96a66cSDavid du Colombier Tnode*
initxsuper(void)3965e96a66cSDavid du Colombier initxsuper(void)
3975e96a66cSDavid du Colombier {
3985e96a66cSDavid du Colombier Block *b;
3995e96a66cSDavid du Colombier Tnode *t;
4005e96a66cSDavid du Colombier
4015e96a66cSDavid du Colombier b = readBlock(PartSuper, 0);
4025e96a66cSDavid du Colombier if(b == nil)
4035e96a66cSDavid du Colombier return stringnode("reading super: %r");
4045e96a66cSDavid du Colombier if(!superUnpack(&super, b->data)){
4055e96a66cSDavid du Colombier blockPut(b);
4065e96a66cSDavid du Colombier return stringnode("unpacking super: %R");
4075e96a66cSDavid du Colombier }
4085e96a66cSDavid du Colombier blockPut(b);
4095e96a66cSDavid du Colombier t = stringnode("super "
4105e96a66cSDavid du Colombier "version=%#ux "
4115e96a66cSDavid du Colombier "epoch=[%#ux,%#ux) "
4125e96a66cSDavid du Colombier "qid=%#llux "
4135e96a66cSDavid du Colombier "active=%#x "
4145e96a66cSDavid du Colombier "next=%#x "
4155e96a66cSDavid du Colombier "current=%#x "
4165e96a66cSDavid du Colombier "last=%V "
4175e96a66cSDavid du Colombier "name=%s",
4185e96a66cSDavid du Colombier super.version, super.epochLow, super.epochHigh,
4195e96a66cSDavid du Colombier super.qid, super.active, super.next, super.current,
4205e96a66cSDavid du Colombier super.last, super.name);
4215e96a66cSDavid du Colombier t->expand = xsuperexpand;
4225e96a66cSDavid du Colombier return t;
4235e96a66cSDavid du Colombier }
4245e96a66cSDavid du Colombier
4255e96a66cSDavid du Colombier void
xvacrootexpand(Tnode * t)4265e96a66cSDavid du Colombier xvacrootexpand(Tnode *t)
4275e96a66cSDavid du Colombier {
4285e96a66cSDavid du Colombier if(t->nkid >= 0)
4295e96a66cSDavid du Colombier return;
4305e96a66cSDavid du Colombier
4315e96a66cSDavid du Colombier t->nkid = 1;
4325e96a66cSDavid du Colombier t->kid = mallocz(sizeof(t->kid[0])*t->nkid, 1);
4335e96a66cSDavid du Colombier t->kid[0] = initxroot("root", vac.score);
4345e96a66cSDavid du Colombier }
4355e96a66cSDavid du Colombier
4365e96a66cSDavid du Colombier Tnode*
initxvacroot(uchar score[VtScoreSize])4375e96a66cSDavid du Colombier initxvacroot(uchar score[VtScoreSize])
4385e96a66cSDavid du Colombier {
4395e96a66cSDavid du Colombier Tnode *t;
4405e96a66cSDavid du Colombier uchar buf[VtRootSize];
4415e96a66cSDavid du Colombier int n;
4425e96a66cSDavid du Colombier
4435e96a66cSDavid du Colombier if((n = vtRead(z, score, VtRootType, buf, VtRootSize)) < 0)
4445e96a66cSDavid du Colombier return stringnode("reading root %V: %R", score);
4455e96a66cSDavid du Colombier
4465e96a66cSDavid du Colombier if(!vtRootUnpack(&vac, buf))
4475e96a66cSDavid du Colombier return stringnode("unpack %d-byte root: %R", n);
4485e96a66cSDavid du Colombier
4495e96a66cSDavid du Colombier h.blockSize = vac.blockSize;
4505e96a66cSDavid du Colombier t = stringnode("vac version=%#ux name=%s type=%s blockSize=%ud score=%V prev=%V",
4515e96a66cSDavid du Colombier vac.version, vac.name, vac.type, vac.blockSize, vac.score, vac.prev);
4525e96a66cSDavid du Colombier t->expand = xvacrootexpand;
4535e96a66cSDavid du Colombier return t;
4545e96a66cSDavid du Colombier }
4555e96a66cSDavid du Colombier
4565e96a66cSDavid du Colombier Tnode*
initxlabel(Label l)4575e96a66cSDavid du Colombier initxlabel(Label l)
4585e96a66cSDavid du Colombier {
4595e96a66cSDavid du Colombier return stringnode("label type=%s state=%s epoch=%#ux tag=%#ux",
4605e96a66cSDavid du Colombier btStr(l.type), bsStr(l.state), l.epoch, l.tag);
4615e96a66cSDavid du Colombier }
4625e96a66cSDavid du Colombier
4635e96a66cSDavid du Colombier typedef struct Xblock Xblock;
4645e96a66cSDavid du Colombier struct Xblock
4655e96a66cSDavid du Colombier {
4665e96a66cSDavid du Colombier Tnode;
4675e96a66cSDavid du Colombier Block *b;
4685e96a66cSDavid du Colombier int (*gen)(void*, Block*, int, Tnode**);
4695e96a66cSDavid du Colombier void *arg;
4705e96a66cSDavid du Colombier int printlabel;
4715e96a66cSDavid du Colombier };
4725e96a66cSDavid du Colombier
4735e96a66cSDavid du Colombier void
xblockexpand(Tnode * tt)4745e96a66cSDavid du Colombier xblockexpand(Tnode *tt)
4755e96a66cSDavid du Colombier {
4765e96a66cSDavid du Colombier int i, j;
4775e96a66cSDavid du Colombier enum { Q = 32 };
4785e96a66cSDavid du Colombier Xblock *t = (Xblock*)tt;
4795e96a66cSDavid du Colombier Tnode *nn;
4805e96a66cSDavid du Colombier
4815e96a66cSDavid du Colombier if(t->nkid >= 0)
4825e96a66cSDavid du Colombier return;
4835e96a66cSDavid du Colombier
4845e96a66cSDavid du Colombier j = 0;
4855e96a66cSDavid du Colombier if(t->printlabel){
4865e96a66cSDavid du Colombier t->kid = mallocz(Q*sizeof(t->kid[0]), 1);
4875e96a66cSDavid du Colombier t->kid[0] = initxlabel(t->b->l);
4885e96a66cSDavid du Colombier j = 1;
4895e96a66cSDavid du Colombier }
4905e96a66cSDavid du Colombier
4915e96a66cSDavid du Colombier for(i=0;; i++){
4925e96a66cSDavid du Colombier switch((*t->gen)(t->arg, t->b, i, &nn)){
4935e96a66cSDavid du Colombier case -1:
4945e96a66cSDavid du Colombier t->nkid = j;
4955e96a66cSDavid du Colombier return;
4965e96a66cSDavid du Colombier case 0:
4975e96a66cSDavid du Colombier break;
4985e96a66cSDavid du Colombier case 1:
4995e96a66cSDavid du Colombier if(j%Q == 0)
5005e96a66cSDavid du Colombier t->kid = realloc(t->kid, (j+Q)*sizeof(t->kid[0]));
5015e96a66cSDavid du Colombier t->kid[j++] = nn;
5025e96a66cSDavid du Colombier break;
5035e96a66cSDavid du Colombier }
5045e96a66cSDavid du Colombier }
5055e96a66cSDavid du Colombier }
5065e96a66cSDavid du Colombier
5075e96a66cSDavid du Colombier int
nilgen(void *,Block *,int,Tnode **)5085e96a66cSDavid du Colombier nilgen(void*, Block*, int, Tnode**)
5095e96a66cSDavid du Colombier {
5105e96a66cSDavid du Colombier return -1;
5115e96a66cSDavid du Colombier }
5125e96a66cSDavid du Colombier
5135e96a66cSDavid du Colombier Tnode*
initxblock(Block * b,char * s,int (* gen)(void *,Block *,int,Tnode **),void * arg)5145e96a66cSDavid du Colombier initxblock(Block *b, char *s, int (*gen)(void*, Block*, int, Tnode**), void *arg)
5155e96a66cSDavid du Colombier {
5165e96a66cSDavid du Colombier Xblock *t;
5175e96a66cSDavid du Colombier
5185e96a66cSDavid du Colombier if(gen == nil)
5195e96a66cSDavid du Colombier gen = nilgen;
5205e96a66cSDavid du Colombier t = mallocz(sizeof(Xblock), 1);
5215e96a66cSDavid du Colombier t->b = b;
5225e96a66cSDavid du Colombier t->gen = gen;
5235e96a66cSDavid du Colombier t->arg = arg;
5245e96a66cSDavid du Colombier if(b->addr == NilBlock)
5255e96a66cSDavid du Colombier t->str = smprint("Block %V: %s", b->score, s);
5265e96a66cSDavid du Colombier else
5275e96a66cSDavid du Colombier t->str = smprint("Block %#ux: %s", b->addr, s);
5285e96a66cSDavid du Colombier t->printlabel = 1;
5295e96a66cSDavid du Colombier t->nkid = -1;
5305e96a66cSDavid du Colombier t->expand = xblockexpand;
5315e96a66cSDavid du Colombier return t;
5325e96a66cSDavid du Colombier }
5335e96a66cSDavid du Colombier
5345e96a66cSDavid du Colombier int
xentrygen(void * v,Block * b,int o,Tnode ** tp)5355e96a66cSDavid du Colombier xentrygen(void *v, Block *b, int o, Tnode **tp)
5365e96a66cSDavid du Colombier {
5375e96a66cSDavid du Colombier Entry e;
5385e96a66cSDavid du Colombier Entry *ed;
5395e96a66cSDavid du Colombier
5405e96a66cSDavid du Colombier ed = v;
5415e96a66cSDavid du Colombier if(o >= ed->dsize/VtEntrySize)
5425e96a66cSDavid du Colombier return -1;
5435e96a66cSDavid du Colombier
5445e96a66cSDavid du Colombier entryUnpack(&e, b->data, o);
5455e96a66cSDavid du Colombier if(!showinactive && !(e.flags & VtEntryActive))
5465e96a66cSDavid du Colombier return 0;
5475e96a66cSDavid du Colombier *tp = initxentry(e);
5485e96a66cSDavid du Colombier return 1;
5495e96a66cSDavid du Colombier }
5505e96a66cSDavid du Colombier
5515e96a66cSDavid du Colombier Tnode*
initxentryblock(Block * b,Entry * ed)5525e96a66cSDavid du Colombier initxentryblock(Block *b, Entry *ed)
5535e96a66cSDavid du Colombier {
5545e96a66cSDavid du Colombier return initxblock(b, "entry", xentrygen, ed);
5555e96a66cSDavid du Colombier }
5565e96a66cSDavid du Colombier
5575e96a66cSDavid du Colombier typedef struct Xentry Xentry;
5585e96a66cSDavid du Colombier struct Xentry
5595e96a66cSDavid du Colombier {
5605e96a66cSDavid du Colombier Tnode;
5615e96a66cSDavid du Colombier Entry e;
5625e96a66cSDavid du Colombier };
5635e96a66cSDavid du Colombier
5645e96a66cSDavid du Colombier void
xentryexpand(Tnode * tt)5655e96a66cSDavid du Colombier xentryexpand(Tnode *tt)
5665e96a66cSDavid du Colombier {
5675e96a66cSDavid du Colombier Xentry *t = (Xentry*)tt;
5685e96a66cSDavid du Colombier
5695e96a66cSDavid du Colombier if(t->nkid >= 0)
5705e96a66cSDavid du Colombier return;
5715e96a66cSDavid du Colombier
5725e96a66cSDavid du Colombier t->nkid = 1;
5735e96a66cSDavid du Colombier t->kid = mallocz(sizeof(t->kid[0])*t->nkid, 1);
5745e96a66cSDavid du Colombier t->kid[0] = initxsource(t->e, 1);
5755e96a66cSDavid du Colombier }
5765e96a66cSDavid du Colombier
5775e96a66cSDavid du Colombier Tnode*
initxentry(Entry e)5785e96a66cSDavid du Colombier initxentry(Entry e)
5795e96a66cSDavid du Colombier {
5805e96a66cSDavid du Colombier Xentry *t;
5815e96a66cSDavid du Colombier
5825e96a66cSDavid du Colombier t = mallocz(sizeof *t, 1);
5835e96a66cSDavid du Colombier t->nkid = -1;
5845e96a66cSDavid du Colombier t->str = smprint("Entry gen=%#ux psize=%d dsize=%d depth=%d flags=%#ux size=%lld score=%V",
5855e96a66cSDavid du Colombier e.gen, e.psize, e.dsize, e.depth, e.flags, e.size, e.score);
5865e96a66cSDavid du Colombier if(e.flags & VtEntryLocal)
5875e96a66cSDavid du Colombier t->str = smprint("%s archive=%d snap=%d tag=%#ux", t->str, e.archive, e.snap, e.tag);
5885e96a66cSDavid du Colombier t->expand = xentryexpand;
5895e96a66cSDavid du Colombier t->e = e;
5905e96a66cSDavid du Colombier return t;
5915e96a66cSDavid du Colombier }
5925e96a66cSDavid du Colombier
5935e96a66cSDavid du Colombier int
ptrgen(void * v,Block * b,int o,Tnode ** tp)5945e96a66cSDavid du Colombier ptrgen(void *v, Block *b, int o, Tnode **tp)
5955e96a66cSDavid du Colombier {
5965e96a66cSDavid du Colombier Entry *ed;
5975e96a66cSDavid du Colombier Entry e;
5985e96a66cSDavid du Colombier
5995e96a66cSDavid du Colombier ed = v;
6005e96a66cSDavid du Colombier if(o >= ed->psize/VtScoreSize)
6015e96a66cSDavid du Colombier return -1;
6025e96a66cSDavid du Colombier
6035e96a66cSDavid du Colombier e = *ed;
6045e96a66cSDavid du Colombier e.depth--;
6055e96a66cSDavid du Colombier memmove(e.score, b->data+o*VtScoreSize, VtScoreSize);
6065e96a66cSDavid du Colombier if(memcmp(e.score, vtZeroScore, VtScoreSize) == 0)
6075e96a66cSDavid du Colombier return 0;
6085e96a66cSDavid du Colombier *tp = initxsource(e, 0);
6095e96a66cSDavid du Colombier return 1;
6105e96a66cSDavid du Colombier }
6115e96a66cSDavid du Colombier
6125e96a66cSDavid du Colombier static int
etype(int flags,int depth)6135e96a66cSDavid du Colombier etype(int flags, int depth)
6145e96a66cSDavid du Colombier {
6155e96a66cSDavid du Colombier uint t;
6165e96a66cSDavid du Colombier
6175e96a66cSDavid du Colombier if(flags&VtEntryDir)
6185e96a66cSDavid du Colombier t = BtDir;
6195e96a66cSDavid du Colombier else
6205e96a66cSDavid du Colombier t = BtData;
6215e96a66cSDavid du Colombier return t+depth;
6225e96a66cSDavid du Colombier }
6235e96a66cSDavid du Colombier
6245e96a66cSDavid du Colombier Tnode*
initxsource(Entry e,int dowrap)6255e96a66cSDavid du Colombier initxsource(Entry e, int dowrap)
6265e96a66cSDavid du Colombier {
6275e96a66cSDavid du Colombier Block *b;
6285e96a66cSDavid du Colombier Tnode *t, *tt;
6295e96a66cSDavid du Colombier
6305e96a66cSDavid du Colombier b = dataBlock(e.score, etype(e.flags, e.depth), e.tag);
6315e96a66cSDavid du Colombier if(b == nil)
6325e96a66cSDavid du Colombier return stringnode("dataBlock: %r");
6335e96a66cSDavid du Colombier
6345e96a66cSDavid du Colombier if((e.flags & VtEntryActive) == 0)
6355e96a66cSDavid du Colombier return stringnode("inactive Entry");
6365e96a66cSDavid du Colombier
6375e96a66cSDavid du Colombier if(e.depth == 0){
6385e96a66cSDavid du Colombier if(e.flags & VtEntryDir)
6395e96a66cSDavid du Colombier tt = initxentryblock(b, copyEntry(e));
6405e96a66cSDavid du Colombier else
6415e96a66cSDavid du Colombier tt = initxdatablock(b, e.dsize);
6425e96a66cSDavid du Colombier }else{
6435e96a66cSDavid du Colombier tt = initxblock(b, smprint("%s+%d pointer", (e.flags & VtEntryDir) ? "BtDir" : "BtData", e.depth),
6445e96a66cSDavid du Colombier ptrgen, copyEntry(e));
6455e96a66cSDavid du Colombier }
6465e96a66cSDavid du Colombier
6475e96a66cSDavid du Colombier /*
6485e96a66cSDavid du Colombier * wrap the contents of the Source in a Source node,
6495e96a66cSDavid du Colombier * just so it's closer to what you see in the code.
6505e96a66cSDavid du Colombier */
6515e96a66cSDavid du Colombier if(dowrap){
6525e96a66cSDavid du Colombier t = stringnode("Source");
6535e96a66cSDavid du Colombier t->nkid = 1;
6545e96a66cSDavid du Colombier t->kid = mallocz(sizeof(Tnode*)*1, 1);
6555e96a66cSDavid du Colombier t->kid[0] = tt;
6565e96a66cSDavid du Colombier tt = t;
6575e96a66cSDavid du Colombier }
6585e96a66cSDavid du Colombier return tt;
6595e96a66cSDavid du Colombier }
6605e96a66cSDavid du Colombier
6615e96a66cSDavid du Colombier int
xlocalrootgen(void *,Block * b,int o,Tnode ** tp)6625e96a66cSDavid du Colombier xlocalrootgen(void*, Block *b, int o, Tnode **tp)
6635e96a66cSDavid du Colombier {
6645e96a66cSDavid du Colombier Entry e;
6655e96a66cSDavid du Colombier
6665e96a66cSDavid du Colombier if(o >= 1)
6675e96a66cSDavid du Colombier return -1;
6685e96a66cSDavid du Colombier entryUnpack(&e, b->data, o);
6695e96a66cSDavid du Colombier *tp = initxentry(e);
6705e96a66cSDavid du Colombier return 1;
6715e96a66cSDavid du Colombier }
6725e96a66cSDavid du Colombier
6735e96a66cSDavid du Colombier Tnode*
initxlocalroot(char * name,u32int addr)6745e96a66cSDavid du Colombier initxlocalroot(char *name, u32int addr)
6755e96a66cSDavid du Colombier {
6765e96a66cSDavid du Colombier uchar score[VtScoreSize];
6775e96a66cSDavid du Colombier Block *b;
6785e96a66cSDavid du Colombier
6795e96a66cSDavid du Colombier localToGlobal(addr, score);
6805e96a66cSDavid du Colombier b = dataBlock(score, BtDir, RootTag);
6815e96a66cSDavid du Colombier if(b == nil)
6825e96a66cSDavid du Colombier return stringnode("read data block %#ux: %R", addr);
6835e96a66cSDavid du Colombier return initxblock(b, smprint("'%s' fs root", name), xlocalrootgen, nil);
6845e96a66cSDavid du Colombier }
6855e96a66cSDavid du Colombier
6865e96a66cSDavid du Colombier int
xvacrootgen(void *,Block * b,int o,Tnode ** tp)6875e96a66cSDavid du Colombier xvacrootgen(void*, Block *b, int o, Tnode **tp)
6885e96a66cSDavid du Colombier {
6895e96a66cSDavid du Colombier Entry e;
6905e96a66cSDavid du Colombier
6915e96a66cSDavid du Colombier if(o >= 3)
6925e96a66cSDavid du Colombier return -1;
6935e96a66cSDavid du Colombier entryUnpack(&e, b->data, o);
6945e96a66cSDavid du Colombier *tp = initxentry(e);
6955e96a66cSDavid du Colombier return 1;
6965e96a66cSDavid du Colombier }
6975e96a66cSDavid du Colombier
6985e96a66cSDavid du Colombier Tnode*
initxroot(char * name,uchar score[VtScoreSize])6995e96a66cSDavid du Colombier initxroot(char *name, uchar score[VtScoreSize])
7005e96a66cSDavid du Colombier {
7015e96a66cSDavid du Colombier Block *b;
7025e96a66cSDavid du Colombier
7035e96a66cSDavid du Colombier b = dataBlock(score, BtDir, RootTag);
7045e96a66cSDavid du Colombier if(b == nil)
7055e96a66cSDavid du Colombier return stringnode("read data block %V: %R", score);
7065e96a66cSDavid du Colombier return initxblock(b, smprint("'%s' fs root", name), xvacrootgen, nil);
7075e96a66cSDavid du Colombier }
7085e96a66cSDavid du Colombier Tnode*
initxdirentry(MetaEntry * me)7095e96a66cSDavid du Colombier initxdirentry(MetaEntry *me)
7105e96a66cSDavid du Colombier {
7115e96a66cSDavid du Colombier DirEntry dir;
7125e96a66cSDavid du Colombier Tnode *t;
7135e96a66cSDavid du Colombier
7145e96a66cSDavid du Colombier if(!deUnpack(&dir, me))
7155e96a66cSDavid du Colombier return stringnode("deUnpack: %R");
7165e96a66cSDavid du Colombier
7175e96a66cSDavid du Colombier t = stringnode("dirEntry elem=%s size=%llud data=%#lux/%#lux meta=%#lux/%#lux", dir.elem, dir.size, dir.entry, dir.gen, dir.mentry, dir.mgen);
7185e96a66cSDavid du Colombier t->nkid = 1;
7195e96a66cSDavid du Colombier t->kid = mallocz(sizeof(t->kid[0])*1, 1);
7205e96a66cSDavid du Colombier t->kid[0] = stringnode(
7215e96a66cSDavid du Colombier "qid=%#llux\n"
7225e96a66cSDavid du Colombier "uid=%s gid=%s mid=%s\n"
7235e96a66cSDavid du Colombier "mtime=%lud mcount=%lud ctime=%lud atime=%lud\n"
7245e96a66cSDavid du Colombier "mode=%luo\n"
7255e96a66cSDavid du Colombier "plan9 %d p9path %#llux p9version %lud\n"
7265e96a66cSDavid du Colombier "qidSpace %d offset %#llux max %#llux",
7275e96a66cSDavid du Colombier dir.qid,
7285e96a66cSDavid du Colombier dir.uid, dir.gid, dir.mid,
7295e96a66cSDavid du Colombier dir.mtime, dir.mcount, dir.ctime, dir.atime,
7305e96a66cSDavid du Colombier dir.mode,
7315e96a66cSDavid du Colombier dir.plan9, dir.p9path, dir.p9version,
7325e96a66cSDavid du Colombier dir.qidSpace, dir.qidOffset, dir.qidMax);
7335e96a66cSDavid du Colombier return t;
7345e96a66cSDavid du Colombier }
7355e96a66cSDavid du Colombier
7365e96a66cSDavid du Colombier int
metaentrygen(void * v,Block *,int o,Tnode ** tp)7375e96a66cSDavid du Colombier metaentrygen(void *v, Block*, int o, Tnode **tp)
7385e96a66cSDavid du Colombier {
7395e96a66cSDavid du Colombier Tnode *t;
7405e96a66cSDavid du Colombier MetaBlock *mb;
7415e96a66cSDavid du Colombier MetaEntry me;
7425e96a66cSDavid du Colombier
7435e96a66cSDavid du Colombier mb = v;
7445e96a66cSDavid du Colombier if(o >= mb->nindex)
7455e96a66cSDavid du Colombier return -1;
7465e96a66cSDavid du Colombier meUnpack(&me, mb, o);
7475e96a66cSDavid du Colombier
7485e96a66cSDavid du Colombier t = stringnode("MetaEntry %d bytes", mb->size);
7495e96a66cSDavid du Colombier t->kid = mallocz(sizeof(t->kid[0])*1, 1);
7505e96a66cSDavid du Colombier t->kid[0] = initxdirentry(&me);
7515e96a66cSDavid du Colombier t->nkid = 1;
7525e96a66cSDavid du Colombier *tp = t;
7535e96a66cSDavid du Colombier return 1;
7545e96a66cSDavid du Colombier }
7555e96a66cSDavid du Colombier
7565e96a66cSDavid du Colombier int
metablockgen(void * v,Block * b,int o,Tnode ** tp)7575e96a66cSDavid du Colombier metablockgen(void *v, Block *b, int o, Tnode **tp)
7585e96a66cSDavid du Colombier {
7595e96a66cSDavid du Colombier Xblock *t;
7605e96a66cSDavid du Colombier MetaBlock *mb;
7615e96a66cSDavid du Colombier
7625e96a66cSDavid du Colombier if(o >= 1)
7635e96a66cSDavid du Colombier return -1;
7645e96a66cSDavid du Colombier
7655e96a66cSDavid du Colombier /* hack: reuse initxblock as a generic iterator */
7665e96a66cSDavid du Colombier mb = v;
7675e96a66cSDavid du Colombier t = (Xblock*)initxblock(b, "", metaentrygen, mb);
7685e96a66cSDavid du Colombier t->str = smprint("MetaBlock %d/%d space used, %d add'l free %d/%d table used%s",
7695e96a66cSDavid du Colombier mb->size, mb->maxsize, mb->free, mb->nindex, mb->maxindex,
7705e96a66cSDavid du Colombier mb->botch ? " [BOTCH]" : "");
7715e96a66cSDavid du Colombier t->printlabel = 0;
7725e96a66cSDavid du Colombier *tp = t;
7735e96a66cSDavid du Colombier return 1;
7745e96a66cSDavid du Colombier }
7755e96a66cSDavid du Colombier
7765e96a66cSDavid du Colombier /*
7775e96a66cSDavid du Colombier * attempt to guess at the type of data in the block.
7785e96a66cSDavid du Colombier * it could just be data from a file, but we're hoping it's MetaBlocks.
7795e96a66cSDavid du Colombier */
7805e96a66cSDavid du Colombier Tnode*
initxdatablock(Block * b,uint n)7815e96a66cSDavid du Colombier initxdatablock(Block *b, uint n)
7825e96a66cSDavid du Colombier {
7835e96a66cSDavid du Colombier MetaBlock mb;
7845e96a66cSDavid du Colombier
7855e96a66cSDavid du Colombier if(n > h.blockSize)
7865e96a66cSDavid du Colombier n = h.blockSize;
7875e96a66cSDavid du Colombier
7885e96a66cSDavid du Colombier if(mbUnpack(&mb, b->data, n))
7895e96a66cSDavid du Colombier return initxblock(b, "metadata", metablockgen, copyMetaBlock(mb));
7905e96a66cSDavid du Colombier
7915e96a66cSDavid du Colombier return initxblock(b, "data", nil, nil);
7925e96a66cSDavid du Colombier }
7935e96a66cSDavid du Colombier
7945e96a66cSDavid du Colombier int
parseScore(uchar * score,char * buf,int n)7955e96a66cSDavid du Colombier parseScore(uchar *score, char *buf, int n)
7965e96a66cSDavid du Colombier {
7975e96a66cSDavid du Colombier int i, c;
7985e96a66cSDavid du Colombier
7995e96a66cSDavid du Colombier memset(score, 0, VtScoreSize);
8005e96a66cSDavid du Colombier
8015e96a66cSDavid du Colombier if(n < VtScoreSize*2)
8025e96a66cSDavid du Colombier return 0;
8035e96a66cSDavid du Colombier for(i=0; i<VtScoreSize*2; i++){
8045e96a66cSDavid du Colombier if(buf[i] >= '0' && buf[i] <= '9')
8055e96a66cSDavid du Colombier c = buf[i] - '0';
8065e96a66cSDavid du Colombier else if(buf[i] >= 'a' && buf[i] <= 'f')
8075e96a66cSDavid du Colombier c = buf[i] - 'a' + 10;
8085e96a66cSDavid du Colombier else if(buf[i] >= 'A' && buf[i] <= 'F')
8095e96a66cSDavid du Colombier c = buf[i] - 'A' + 10;
8105e96a66cSDavid du Colombier else{
8115e96a66cSDavid du Colombier return 0;
8125e96a66cSDavid du Colombier }
8135e96a66cSDavid du Colombier
8145e96a66cSDavid du Colombier if((i & 1) == 0)
8155e96a66cSDavid du Colombier c <<= 4;
8165e96a66cSDavid du Colombier
8175e96a66cSDavid du Colombier score[i>>1] |= c;
8185e96a66cSDavid du Colombier }
8195e96a66cSDavid du Colombier return 1;
8205e96a66cSDavid du Colombier }
8215e96a66cSDavid du Colombier
8225e96a66cSDavid du Colombier int
scoreFmt(Fmt * f)8235e96a66cSDavid du Colombier scoreFmt(Fmt *f)
8245e96a66cSDavid du Colombier {
8255e96a66cSDavid du Colombier uchar *v;
8265e96a66cSDavid du Colombier int i;
8275e96a66cSDavid du Colombier u32int addr;
8285e96a66cSDavid du Colombier
8295e96a66cSDavid du Colombier v = va_arg(f->args, uchar*);
8305e96a66cSDavid du Colombier if(v == nil){
8315e96a66cSDavid du Colombier fmtprint(f, "*");
8325e96a66cSDavid du Colombier }else if((addr = globalToLocal(v)) != NilBlock)
8335e96a66cSDavid du Colombier fmtprint(f, "0x%.8ux", addr);
8345e96a66cSDavid du Colombier else{
8355e96a66cSDavid du Colombier for(i = 0; i < VtScoreSize; i++)
8365e96a66cSDavid du Colombier fmtprint(f, "%2.2ux", v[i]);
8375e96a66cSDavid du Colombier }
8385e96a66cSDavid du Colombier
8395e96a66cSDavid du Colombier return 0;
8405e96a66cSDavid du Colombier }
8415e96a66cSDavid du Colombier
8425e96a66cSDavid du Colombier Atree*
atreeinit(char * arg)8435e96a66cSDavid du Colombier atreeinit(char *arg)
8445e96a66cSDavid du Colombier {
8455e96a66cSDavid du Colombier Atree *a;
8465e96a66cSDavid du Colombier uchar score[VtScoreSize];
8475e96a66cSDavid du Colombier
8485e96a66cSDavid du Colombier vtAttach();
8495e96a66cSDavid du Colombier
8505e96a66cSDavid du Colombier fmtinstall('V', scoreFmt);
8515e96a66cSDavid du Colombier fmtinstall('R', vtErrFmt);
8525e96a66cSDavid du Colombier
8535e96a66cSDavid du Colombier z = vtDial(nil, 1);
8545e96a66cSDavid du Colombier if(z == nil)
8555e96a66cSDavid du Colombier fprint(2, "warning: cannot dial venti: %R\n");
8565e96a66cSDavid du Colombier if(!vtConnect(z, 0)){
8575e96a66cSDavid du Colombier fprint(2, "warning: cannot connect to venti: %R\n");
8585e96a66cSDavid du Colombier z = nil;
8595e96a66cSDavid du Colombier }
8605e96a66cSDavid du Colombier a = mallocz(sizeof(Atree), 1);
8615e96a66cSDavid du Colombier if(strncmp(arg, "vac:", 4) == 0){
8625e96a66cSDavid du Colombier if(!parseScore(score, arg+4, strlen(arg+4))){
8635e96a66cSDavid du Colombier fprint(2, "cannot parse score\n");
8645e96a66cSDavid du Colombier return nil;
8655e96a66cSDavid du Colombier }
8665e96a66cSDavid du Colombier a->root = initxvacroot(score);
8675e96a66cSDavid du Colombier }else
8685e96a66cSDavid du Colombier a->root = initxcache(arg);
8695e96a66cSDavid du Colombier a->resizefd = -1;
8705e96a66cSDavid du Colombier return a;
8715e96a66cSDavid du Colombier }
8725e96a66cSDavid du Colombier
8735e96a66cSDavid du Colombier /* --- tree.c */
8745e96a66cSDavid du Colombier enum
8755e96a66cSDavid du Colombier {
8765e96a66cSDavid du Colombier Nubwidth = 11,
8775e96a66cSDavid du Colombier Nubheight = 11,
8785e96a66cSDavid du Colombier Linewidth = Nubwidth*2+4,
8795e96a66cSDavid du Colombier };
8805e96a66cSDavid du Colombier
8815e96a66cSDavid du Colombier uint
drawtext(char * s,Image * m,Image * clipr,Point o)8825e96a66cSDavid du Colombier drawtext(char *s, Image *m, Image *clipr, Point o)
8835e96a66cSDavid du Colombier {
8845e96a66cSDavid du Colombier char *t, *nt, *e;
8855e96a66cSDavid du Colombier uint dy;
8865e96a66cSDavid du Colombier
8875e96a66cSDavid du Colombier if(s == nil)
8885e96a66cSDavid du Colombier s = "???";
8895e96a66cSDavid du Colombier
8905e96a66cSDavid du Colombier dy = 0;
8915e96a66cSDavid du Colombier for(t=s; t&&*t; t=nt){
8925e96a66cSDavid du Colombier if(nt = strchr(t, '\n')){
8935e96a66cSDavid du Colombier e = nt;
8945e96a66cSDavid du Colombier nt++;
8955e96a66cSDavid du Colombier }else
8965e96a66cSDavid du Colombier e = t+strlen(t);
8975e96a66cSDavid du Colombier
8985e96a66cSDavid du Colombier _string(m, Pt(o.x, o.y+dy), display->black, ZP, display->defaultfont,
8995e96a66cSDavid du Colombier t, nil, e-t, clipr->clipr, nil, ZP, SoverD);
9005e96a66cSDavid du Colombier dy += display->defaultfont->height;
9015e96a66cSDavid du Colombier }
9025e96a66cSDavid du Colombier return dy;
9035e96a66cSDavid du Colombier }
9045e96a66cSDavid du Colombier
9055e96a66cSDavid du Colombier void
drawnub(Image * m,Image * clipr,Point o,Tnode * t)9065e96a66cSDavid du Colombier drawnub(Image *m, Image *clipr, Point o, Tnode *t)
9075e96a66cSDavid du Colombier {
9085e96a66cSDavid du Colombier clipr = nil;
9095e96a66cSDavid du Colombier
9105e96a66cSDavid du Colombier if(t->nkid == 0)
9115e96a66cSDavid du Colombier return;
9125e96a66cSDavid du Colombier if(t->nkid == -1 && t->expand == nil)
9135e96a66cSDavid du Colombier return;
9145e96a66cSDavid du Colombier
9155e96a66cSDavid du Colombier o.y += (display->defaultfont->height-Nubheight)/2;
9165e96a66cSDavid du Colombier draw(m, rectaddpt(Rect(0,0,1,Nubheight), o), display->black, clipr, ZP);
9175e96a66cSDavid du Colombier draw(m, rectaddpt(Rect(0,0,Nubwidth,1), o), display->black, clipr, o);
9185e96a66cSDavid du Colombier draw(m, rectaddpt(Rect(Nubwidth-1,0,Nubwidth,Nubheight), o),
9195e96a66cSDavid du Colombier display->black, clipr, addpt(o, Pt(Nubwidth-1, 0)));
9205e96a66cSDavid du Colombier draw(m, rectaddpt(Rect(0, Nubheight-1, Nubwidth, Nubheight), o),
9215e96a66cSDavid du Colombier display->black, clipr, addpt(o, Pt(0, Nubheight-1)));
9225e96a66cSDavid du Colombier
9235e96a66cSDavid du Colombier draw(m, rectaddpt(Rect(0, Nubheight/2, Nubwidth, Nubheight/2+1), o),
9245e96a66cSDavid du Colombier display->black, clipr, addpt(o, Pt(0, Nubheight/2)));
9255e96a66cSDavid du Colombier if(!t->expanded)
9265e96a66cSDavid du Colombier draw(m, rectaddpt(Rect(Nubwidth/2, 0, Nubwidth/2+1, Nubheight), o),
9275e96a66cSDavid du Colombier display->black, clipr, addpt(o, Pt(Nubwidth/2, 0)));
9285e96a66cSDavid du Colombier
9295e96a66cSDavid du Colombier }
9305e96a66cSDavid du Colombier
9315e96a66cSDavid du Colombier uint
drawnode(Tnode * t,Image * m,Image * clipr,Point o)9325e96a66cSDavid du Colombier drawnode(Tnode *t, Image *m, Image *clipr, Point o)
9335e96a66cSDavid du Colombier {
9345e96a66cSDavid du Colombier int i;
9355e96a66cSDavid du Colombier char *fs, *s;
9365e96a66cSDavid du Colombier uint dy;
9375e96a66cSDavid du Colombier Point oo;
9385e96a66cSDavid du Colombier
9395e96a66cSDavid du Colombier if(t == nil)
9405e96a66cSDavid du Colombier return 0;
9415e96a66cSDavid du Colombier
9425e96a66cSDavid du Colombier t->offset = o;
9435e96a66cSDavid du Colombier
9445e96a66cSDavid du Colombier oo = Pt(o.x+Nubwidth+2, o.y);
9455e96a66cSDavid du Colombier // if(t->draw)
9465e96a66cSDavid du Colombier // dy = (*t->draw)(t, m, clipr, oo);
9475e96a66cSDavid du Colombier // else{
9485e96a66cSDavid du Colombier fs = nil;
9495e96a66cSDavid du Colombier if(t->str)
9505e96a66cSDavid du Colombier s = t->str;
9515e96a66cSDavid du Colombier // else if(t->strfn)
9525e96a66cSDavid du Colombier // fs = s = (*t->strfn)(t);
9535e96a66cSDavid du Colombier else
9545e96a66cSDavid du Colombier s = "???";
9555e96a66cSDavid du Colombier dy = drawtext(s, m, clipr, oo);
9565e96a66cSDavid du Colombier free(fs);
9575e96a66cSDavid du Colombier // }
9585e96a66cSDavid du Colombier
9595e96a66cSDavid du Colombier if(t->expanded){
9605e96a66cSDavid du Colombier if(t->nkid == -1 && t->expand)
9615e96a66cSDavid du Colombier (*t->expand)(t);
9625e96a66cSDavid du Colombier oo = Pt(o.x+Nubwidth+(Linewidth-Nubwidth)/2, o.y+dy);
9635e96a66cSDavid du Colombier for(i=0; i<t->nkid; i++)
9645e96a66cSDavid du Colombier oo.y += drawnode(t->kid[i], m, clipr, oo);
9655e96a66cSDavid du Colombier dy = oo.y - o.y;
9665e96a66cSDavid du Colombier }
9675e96a66cSDavid du Colombier drawnub(m, clipr, o, t);
9685e96a66cSDavid du Colombier return dy;
9695e96a66cSDavid du Colombier }
9705e96a66cSDavid du Colombier
9715e96a66cSDavid du Colombier void
drawtree(Tree * t,Image * m,Rectangle r)9725e96a66cSDavid du Colombier drawtree(Tree *t, Image *m, Rectangle r)
9735e96a66cSDavid du Colombier {
9745e96a66cSDavid du Colombier Point p;
9755e96a66cSDavid du Colombier
9765e96a66cSDavid du Colombier draw(m, r, display->white, nil, ZP);
9775e96a66cSDavid du Colombier
9785e96a66cSDavid du Colombier replclipr(t->clipr, 1, r);
9795e96a66cSDavid du Colombier p = addpt(t->offset, r.min);
9805e96a66cSDavid du Colombier drawnode(t->root, m, t->clipr, p);
9815e96a66cSDavid du Colombier }
9825e96a66cSDavid du Colombier
9835e96a66cSDavid du Colombier Tnode*
findnode(Tnode * t,Point p)9845e96a66cSDavid du Colombier findnode(Tnode *t, Point p)
9855e96a66cSDavid du Colombier {
9865e96a66cSDavid du Colombier int i;
9875e96a66cSDavid du Colombier Tnode *tt;
9885e96a66cSDavid du Colombier
9895e96a66cSDavid du Colombier if(ptinrect(p, rectaddpt(Rect(0,0,Nubwidth, Nubheight), t->offset)))
9905e96a66cSDavid du Colombier return t;
9915e96a66cSDavid du Colombier if(!t->expanded)
9925e96a66cSDavid du Colombier return nil;
9935e96a66cSDavid du Colombier for(i=0; i<t->nkid; i++)
9945e96a66cSDavid du Colombier if(tt = findnode(t->kid[i], p))
9955e96a66cSDavid du Colombier return tt;
9965e96a66cSDavid du Colombier return nil;
9975e96a66cSDavid du Colombier }
9985e96a66cSDavid du Colombier
9995e96a66cSDavid du Colombier void
usage(void)10005e96a66cSDavid du Colombier usage(void)
10015e96a66cSDavid du Colombier {
10025e96a66cSDavid du Colombier fprint(2, "usage: vtree /dev/sdC0/fossil\n");
10035e96a66cSDavid du Colombier exits("usage");
10045e96a66cSDavid du Colombier }
10055e96a66cSDavid du Colombier
10065e96a66cSDavid du Colombier Tree t;
10075e96a66cSDavid du Colombier
10085e96a66cSDavid du Colombier void
eresized(int new)10095e96a66cSDavid du Colombier eresized(int new)
10105e96a66cSDavid du Colombier {
10115e96a66cSDavid du Colombier Rectangle r;
10125e96a66cSDavid du Colombier r = screen->r;
10135e96a66cSDavid du Colombier if(new && getwindow(display, Refnone) < 0)
10145e96a66cSDavid du Colombier fprint(2,"can't reattach to window");
10155e96a66cSDavid du Colombier drawtree(&t, screen, screen->r);
10165e96a66cSDavid du Colombier }
10175e96a66cSDavid du Colombier
10185e96a66cSDavid du Colombier enum
10195e96a66cSDavid du Colombier {
10205e96a66cSDavid du Colombier Left = 1<<0,
10215e96a66cSDavid du Colombier Middle = 1<<1,
10225e96a66cSDavid du Colombier Right = 1<<2,
10235e96a66cSDavid du Colombier
10245e96a66cSDavid du Colombier MMenu = 2,
10255e96a66cSDavid du Colombier };
10265e96a66cSDavid du Colombier
10275e96a66cSDavid du Colombier char *items[] = { "exit", 0 };
10285e96a66cSDavid du Colombier enum { IExit, };
10295e96a66cSDavid du Colombier
10305e96a66cSDavid du Colombier Menu menu;
10315e96a66cSDavid du Colombier
10325e96a66cSDavid du Colombier void
main(int argc,char ** argv)10335e96a66cSDavid du Colombier main(int argc, char **argv)
10345e96a66cSDavid du Colombier {
10355e96a66cSDavid du Colombier int n;
10365e96a66cSDavid du Colombier char *dir;
10375e96a66cSDavid du Colombier Event e;
10385e96a66cSDavid du Colombier Point op, p;
10395e96a66cSDavid du Colombier Tnode *tn;
10405e96a66cSDavid du Colombier Mouse m;
10415e96a66cSDavid du Colombier int Eready;
10425e96a66cSDavid du Colombier Atree *fs;
10435e96a66cSDavid du Colombier
10445e96a66cSDavid du Colombier ARGBEGIN{
10455e96a66cSDavid du Colombier case 'a':
10465e96a66cSDavid du Colombier showinactive = 1;
10475e96a66cSDavid du Colombier break;
10485e96a66cSDavid du Colombier default:
10495e96a66cSDavid du Colombier usage();
10505e96a66cSDavid du Colombier }ARGEND
10515e96a66cSDavid du Colombier
10525e96a66cSDavid du Colombier switch(argc){
10535e96a66cSDavid du Colombier default:
10545e96a66cSDavid du Colombier usage();
10555e96a66cSDavid du Colombier case 1:
10565e96a66cSDavid du Colombier dir = argv[0];
10575e96a66cSDavid du Colombier break;
10585e96a66cSDavid du Colombier }
10595e96a66cSDavid du Colombier
10605e96a66cSDavid du Colombier fs = atreeinit(dir);
10615e96a66cSDavid du Colombier initdraw(0, "/lib/font/bit/lucidasans/unicode.8.font", "tree");
10625e96a66cSDavid du Colombier t.root = fs->root;
10635e96a66cSDavid du Colombier t.offset = ZP;
10645e96a66cSDavid du Colombier t.clipr = allocimage(display, Rect(0,0,1,1), GREY1, 1, DOpaque);
10655e96a66cSDavid du Colombier
10665e96a66cSDavid du Colombier eresized(0);
10675e96a66cSDavid du Colombier flushimage(display, 1);
10685e96a66cSDavid du Colombier
10695e96a66cSDavid du Colombier einit(Emouse);
10705e96a66cSDavid du Colombier
10715e96a66cSDavid du Colombier menu.item = items;
10725e96a66cSDavid du Colombier menu.gen = 0;
10735e96a66cSDavid du Colombier menu.lasthit = 0;
10745e96a66cSDavid du Colombier if(fs->resizefd > 0){
10755e96a66cSDavid du Colombier Eready = 1<<3;
10765e96a66cSDavid du Colombier estart(Eready, fs->resizefd, 1);
10775e96a66cSDavid du Colombier }else
10785e96a66cSDavid du Colombier Eready = 0;
10795e96a66cSDavid du Colombier
10805e96a66cSDavid du Colombier for(;;){
10815e96a66cSDavid du Colombier switch(n=eread(Emouse|Eready, &e)){
10825e96a66cSDavid du Colombier default:
10835e96a66cSDavid du Colombier if(Eready && n==Eready)
10845e96a66cSDavid du Colombier eresized(0);
10855e96a66cSDavid du Colombier break;
10865e96a66cSDavid du Colombier case Emouse:
10875e96a66cSDavid du Colombier m = e.mouse;
10885e96a66cSDavid du Colombier switch(m.buttons){
10895e96a66cSDavid du Colombier case Left:
10905e96a66cSDavid du Colombier op = t.offset;
10915e96a66cSDavid du Colombier p = m.xy;
10925e96a66cSDavid du Colombier do {
10935e96a66cSDavid du Colombier t.offset = addpt(t.offset, subpt(m.xy, p));
10945e96a66cSDavid du Colombier p = m.xy;
10955e96a66cSDavid du Colombier eresized(0);
10965e96a66cSDavid du Colombier m = emouse();
10975e96a66cSDavid du Colombier }while(m.buttons == Left);
10985e96a66cSDavid du Colombier if(m.buttons){
10995e96a66cSDavid du Colombier t.offset = op;
11005e96a66cSDavid du Colombier eresized(0);
11015e96a66cSDavid du Colombier }
11025e96a66cSDavid du Colombier break;
11035e96a66cSDavid du Colombier case Middle:
11045e96a66cSDavid du Colombier n = emenuhit(MMenu, &m, &menu);
11055e96a66cSDavid du Colombier if(n == -1)
11065e96a66cSDavid du Colombier break;
11075e96a66cSDavid du Colombier switch(n){
11085e96a66cSDavid du Colombier case IExit:
11095e96a66cSDavid du Colombier exits(nil);
11105e96a66cSDavid du Colombier }
11115e96a66cSDavid du Colombier break;
11125e96a66cSDavid du Colombier case Right:
11135e96a66cSDavid du Colombier do
11145e96a66cSDavid du Colombier m = emouse();
11155e96a66cSDavid du Colombier while(m.buttons == Right);
11165e96a66cSDavid du Colombier if(m.buttons)
11175e96a66cSDavid du Colombier break;
11185e96a66cSDavid du Colombier tn = findnode(t.root, m.xy);
11195e96a66cSDavid du Colombier if(tn){
11205e96a66cSDavid du Colombier tn->expanded = !tn->expanded;
11215e96a66cSDavid du Colombier eresized(0);
11225e96a66cSDavid du Colombier }
11235e96a66cSDavid du Colombier break;
11245e96a66cSDavid du Colombier }
11255e96a66cSDavid du Colombier }
11265e96a66cSDavid du Colombier }
11275e96a66cSDavid du Colombier }
1128