display.c 4.43 KB
Newer Older
1 2 3
/* $Id$ $Revision$ */
/* vim:set shiftwidth=4 ts=8: */

ellson's avatar
ellson committed
4 5 6 7 8 9 10 11 12
/*************************************************************************
 * Copyright (c) 2011 AT&T Intellectual Property 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors: See CVS logs. Details at http://www.graphviz.org/
 *************************************************************************/
13

14
/* Lefteris Koutsofios - AT&T Labs Research */
15 16 17 18 19 20 21 22 23

#include "common.h"
#include "mem.h"
#include "code.h"
#include "tbl.h"
#include "str.h"
#include "display.h"

typedef struct dnode_t {
24
    int ttype;
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
    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;

40 41 42 43 44
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 *);
45

46 47
void Dinit (void) {
    seenp = Marrayalloc ((long) SEENINCR * SEENSIZE);
48 49 50 51
    seeni = 0;
    seenn = SEENINCR;
}

52 53
void Dterm (void) {
    Marrayfree (seenp);
54 55 56
    seeni = seenn = 0;
}

57
void Dtrace (Tobj to, int offset) {
58 59 60 61 62 63
    dnode_t dnode;
    char *s;
    int i;

    indent = offset - 2;
    afternl = TRUE;
64 65 66
    if (Tgettype (to) != T_TABLE) {
        pr ((s = Ssfull (NULL, to))), free (s);
        return;
67 68 69 70 71
    }

    seeni = 0;
    dnode.vo = to;
    dnode.path = "";
72
    update (&dnode);
73
    for (i = 0; i < seeni; i++)
74
        free (seenp[i].path), seenp[i].path = NULL;
75 76
}

77
static void update (dnode_t *pnode) {
78 79 80 81 82 83 84 85
    Tkvindex_t tkvi;
    dnode_t *list, *cnode;
    seennode_t *seennode;
    char *s;
    long i, n;

    indent += 2;
    n = ((Ttable_t *) pnode->vo)->n;
86
    if (!(list = malloc (n * sizeof (dnode_t))))
87
        panic1 (POS, "update", "list malloc failed");
88 89 90 91 92 93 94
    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);
95
    }
96
    qsort ((char *) list, n, sizeof (dnode_t), cmp);
97
    for (i = 0, cnode = &list[0]; i < n; i++, cnode++) {
98 99 100 101 102 103 104 105 106 107 108 109 110 111
        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);
            }
        }
112
    }
113
    free (list);
114 115 116
    indent -= 2;
}

117 118
static int cmp (const void *a, const void *b) {
    int atype, btype;
119
    dnode_t *anode, *bnode;
120
    double d1, d2;
121

122
    d1 = 0.0, d2 = 0.0;
123
    anode = (dnode_t *) a, bnode = (dnode_t *) b;
124
    atype = Tgettype (anode->ko), btype = Tgettype (bnode->ko);
125
    if (atype != btype)
126
        return (atype - btype);
127
    if (atype == T_STRING)
128
        return strcmp (Tgetstring (anode->ko), Tgetstring (bnode->ko));
129
    if (atype == T_INTEGER)
130
        d1 = Tgetinteger (anode->ko), d2 = Tgetinteger (bnode->ko);
131
    else if (atype == T_REAL)
132
        d1 = Tgetreal (anode->ko), d2 = Tgetreal (bnode->ko);
133
    if (d1 < d2)
134
        return -1;
135
    else if (d1 > d2)
136
        return 1;
137
    else
138
        return 0; /* but this should never happen since keys are unique */
139 140
}

141
static seennode_t *findseen (dnode_t *cnode) {
142 143 144
    int i;

    for (i = 0; i < seeni; i++)
145 146
        if (seenp[i].vo == cnode->vo)
            return &seenp[i];
147 148 149
    return NULL;
}

150
static void add2seen (dnode_t *cnode) {
151
    if (seeni >= seenn) {
152 153
        seenp = Marraygrow (seenp, (long) (seenn + SEENINCR) * SEENSIZE);
        seenn += SEENINCR;
154 155 156 157 158
    }
    seenp[seeni].vo = cnode->vo;
    seenp[seeni++].path = cnode->path;
}

159
static void pr (char *s) {
160 161 162 163
    char *s1;
    int i;

    for (s1 = s; *s1; s1++) {
164 165 166 167 168 169 170 171
        if (afternl) {
            for (i = 0; i < indent; i++)
                putchar (' ');
            afternl = FALSE;
        }
        if (*s1 == '\n')
            afternl = TRUE;
        putchar ((*s1)); /* HACK: to keep proto happy */
172
    }
173
    putchar ('\n');
174 175
    afternl = TRUE;
}