#pragma prototyped
#include "common.h"
#include "mem.h"
#include "code.h"
#include "tbl.h"
#include "str.h"
#include "display.h"
typedef struct dnode_t {
Ttype_t ttype;
Tobj ko, vo;
char *path;
} dnode_t;
typedef struct seennode_t {
Tobj vo;
char *path;
} seennode_t;
static seennode_t *seenp;
static int seeni, seenn;
#define SEENINCR 100
#define SEENSIZE sizeof (seennode_t)
static int indent, afternl;
static void update (dnode_t *);
static int cmp (const void *, const void *);
static seennode_t *findseen (dnode_t *);
static void add2seen (dnode_t *);
static void pr (char *);
void Dinit (void) {
seenp = Marrayalloc ((long) SEENINCR * SEENSIZE);
seeni = 0;
seenn = SEENINCR;
}
void Dterm (void) {
Marrayfree (seenp);
seeni = seenn = 0;
}
void Dtrace (Tobj to, int offset) {
dnode_t dnode;
char *s;
int i;
indent = offset - 2;
afternl = TRUE;
if (Tgettype (to) != T_TABLE) {
pr ((s = Ssfull (NULL, to))), free (s);
return;
}
seeni = 0;
dnode.vo = to;
dnode.path = "";
update (&dnode);
for (i = 0; i < seeni; i++)
free (seenp[i].path), seenp[i].path = NULL;
}
static void update (dnode_t *pnode) {
Tkvindex_t tkvi;
dnode_t *list, *cnode;
seennode_t *seennode;
char *s;
long i, n;
indent += 2;
n = ((Ttable_t *) pnode->vo)->n;
if (!(list = malloc (n * sizeof (dnode_t))))
panic (POS, "update", "list malloc failed");
for (cnode = &list[0], Tgetfirst (pnode->vo, &tkvi); tkvi.kvp;
cnode++, Tgetnext (&tkvi)) {
cnode->ko = tkvi.kvp->ko;
cnode->vo = tkvi.kvp->vo;
cnode->ttype = Tgettype (cnode->vo);
}
qsort ((char *) list, n, sizeof (dnode_t), cmp);
for (i = 0, cnode = &list[0]; i < n; i++, cnode++) {
cnode->path = Spath (pnode->path, cnode->ko);
seennode = findseen (cnode);
if (seennode) {
pr ((s = Sseen (cnode->ko, seennode->path))), free (s);
} else {
add2seen (cnode);
if (cnode->ttype == T_TABLE) {
pr ((s = Stfull (cnode->ko))), free (s);
update (cnode);
pr ("];");
} else {
pr ((s = Ssfull (cnode->ko, cnode->vo))), free (s);
}
}
}
free (list);
indent -= 2;
}
static int cmp (const void *a, const void *b) {
Ttype_t atype, btype;
dnode_t *anode, *bnode;
double d1 = 0.0, d2 = 0.0;
anode = (dnode_t *) a, bnode = (dnode_t *) b;
atype = Tgettype (anode->ko), btype = Tgettype (bnode->ko);
if (atype != btype)
return (atype - btype);
if (atype == T_STRING)
return Strcmp (Tgetstring (anode->ko), Tgetstring (bnode->ko));
if (atype == T_INTEGER)
d1 = Tgetinteger (anode->ko), d2 = Tgetinteger (bnode->ko);
else if (atype == T_REAL)
d1 = Tgetreal (anode->ko), d2 = Tgetreal (bnode->ko);
if (d1 < d2)
return -1;
else if (d1 > d2)
return 1;
else
return 0;
}
static seennode_t *findseen (dnode_t *cnode) {
int i;
for (i = 0; i < seeni; i++)
if (seenp[i].vo == cnode->vo)
return &seenp[i];
return NULL;
}
static void add2seen (dnode_t *cnode) {
if (seeni >= seenn) {
seenp = Marraygrow (seenp, (long) (seenn + SEENINCR) * SEENSIZE);
seenn += SEENINCR;
}
seenp[seeni].vo = cnode->vo;
seenp[seeni++].path = cnode->path;
}
static void pr (char *s) {
char *s1;
int i;
for (s1 = s; *s1; s1++) {
if (afternl) {
for (i = 0; i < indent; i++)
putchar (' ');
afternl = FALSE;
}
if (*s1 == '\n')
afternl = TRUE;
putchar ((*s1));
}
putchar ('\n');
afternl = TRUE;
}