~ubuntu-branches/ubuntu/precise/graphviz/precise-security

« back to all changes in this revision

Viewing changes to lib/agraph/obj.c

  • Committer: Bazaar Package Importer
  • Author(s): David Claughton
  • Date: 2010-03-24 22:45:18 UTC
  • mfrom: (1.2.7 upstream) (6.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20100324224518-do441tthbqjaqjzd
Tags: 2.26.3-4
Add patch to fix segfault in circo. Backported from upstream snapshot
release.  Thanks to Francis Russell for his work on this.
(Closes: #575255)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: obj.c,v 1.2 2006/07/08 17:33:49 ellson Exp $ $Revision: 1.2 $ */
2
 
/* vim:set shiftwidth=4 ts=8: */
3
 
 
4
 
/**********************************************************
5
 
*      This software is part of the graphviz package      *
6
 
*                http://www.graphviz.org/                 *
7
 
*                                                         *
8
 
*            Copyright (c) 1994-2004 AT&T Corp.           *
9
 
*                and is licensed under the                *
10
 
*            Common Public License, Version 1.0           *
11
 
*                      by AT&T Corp.                      *
12
 
*                                                         *
13
 
*        Information and Software Systems Research        *
14
 
*              AT&T Research, Florham Park NJ             *
15
 
**********************************************************/
16
 
 
17
 
 
18
 
#include "aghdr.h"
19
 
 
20
 
int agobjidcmpf(Dict_t * dict, void *arg0, void *arg1, Dtdisc_t * disc)
21
 
{
22
 
    Agobj_t *obj0, *obj1;
23
 
 
24
 
    NOTUSED(dict);
25
 
    obj0 = arg0;
26
 
    obj1 = arg1;
27
 
    NOTUSED(disc);
28
 
    return AGID(obj0) - AGID(obj1);
29
 
}
30
 
 
31
 
int agobjseqcmpf(Dict_t * dict, void *arg0, void *arg1, Dtdisc_t * disc)
32
 
{
33
 
    Agobj_t *obj0, *obj1;
34
 
 
35
 
    NOTUSED(dict);
36
 
    obj0 = arg0;
37
 
    obj1 = arg1;
38
 
    NOTUSED(disc);
39
 
    return AGSEQ(obj0) - AGSEQ(obj1);
40
 
}
41
 
 
42
 
Agobj_t *agrebind(Agraph_t * g, Agobj_t * obj)
43
 
{
44
 
    Agraph_t *h;
45
 
    Agobj_t *nobj;
46
 
 
47
 
    h = agraphof(obj);
48
 
    if (h == g)
49
 
        return obj;
50
 
 
51
 
    switch (AGTYPE(obj)) {
52
 
    case AGNODE:
53
 
        nobj = (Agobj_t *) agsubnode(g, (Agnode_t *) obj, FALSE);
54
 
        break;
55
 
    case AGINEDGE:
56
 
    case AGOUTEDGE:
57
 
        nobj = (Agobj_t *) agsubedge(g, (Agedge_t *) obj, FALSE);
58
 
        break;
59
 
    case AGRAPH:
60
 
        nobj = (Agobj_t *) g;
61
 
        break;
62
 
    default:
63
 
        nobj = 0;
64
 
        agerror(AGERROR_BADOBJ, "agrebind");
65
 
    }
66
 
    return nobj;
67
 
}
68
 
 
69
 
int agdelete(Agraph_t * g, void *obj)
70
 
{
71
 
    Agraph_t *h;
72
 
 
73
 
    h = agraphof(obj);
74
 
    if ((g != h)
75
 
        && ((AGTYPE((Agobj_t *) obj) != AGRAPH) || (g != agparent(h))))
76
 
        agerror(AGERROR_WRONGGRAPH, "agdelete");
77
 
 
78
 
    switch (AGTYPE((Agobj_t *) obj)) {
79
 
    case AGNODE:
80
 
        return agdelnode(obj);
81
 
    case AGINEDGE:
82
 
    case AGOUTEDGE:
83
 
        return agdeledge(obj);
84
 
    case AGRAPH:
85
 
        return agclose(obj);
86
 
    default:
87
 
        agerror(AGERROR_BADOBJ, "agdelete");
88
 
    }
89
 
    return SUCCESS;             /* not reached */
90
 
}
91
 
 
92
 
int agrename(Agobj_t * obj, char *newname)
93
 
{
94
 
    Agraph_t *g;
95
 
    unsigned long old_id, new_id;
96
 
 
97
 
    switch (AGTYPE(obj)) {
98
 
    case AGRAPH:
99
 
        old_id = AGID(obj);
100
 
        g = agraphof(obj);
101
 
        /* can we reserve the id corresponding to newname? */
102
 
        if (agmapnametoid(agroot(g), AGTYPE(obj), newname,
103
 
                          &new_id, FALSE) == 0)
104
 
            return FAILURE;
105
 
        if (new_id == old_id)
106
 
            return SUCCESS;
107
 
        if (agmapnametoid(agroot(g), AGTYPE(obj), newname,
108
 
                          &new_id, TRUE) == 0)
109
 
            return FAILURE;
110
 
        if (agparent(g) && agidsubg(agparent(g), new_id, 0))
111
 
            return FAILURE;
112
 
        agfreeid(g, AGRAPH, old_id);
113
 
        AGID(g) = new_id;
114
 
        break;
115
 
    case AGNODE:
116
 
        return agrelabel_node((Agnode_t *) obj, newname);
117
 
    case AGINEDGE:
118
 
    case AGOUTEDGE:
119
 
        return FAILURE;
120
 
    }
121
 
    return SUCCESS;
122
 
}
123
 
 
124
 
/* perform initialization/update/finalization method invocation.
125
 
 * skip over nil pointers to next method below.
126
 
 */
127
 
 
128
 
void agmethod_init(Agraph_t * g, void *obj)
129
 
{
130
 
    if (g->clos->callbacks_enabled)
131
 
        aginitcb(obj, g->clos->cb);
132
 
    else
133
 
        agrecord_callback(obj, CB_INITIALIZE, NILsym);
134
 
}
135
 
 
136
 
void aginitcb(void *obj, Agcbstack_t * cbstack)
137
 
{
138
 
    agobjfn_t fn;
139
 
 
140
 
    if (cbstack == NIL(Agcbstack_t *))
141
 
        return;
142
 
    aginitcb(obj, cbstack->prev);
143
 
    fn = NIL(agobjfn_t);
144
 
    switch (AGTYPE(obj)) {
145
 
    case AGRAPH:
146
 
        fn = cbstack->f->graph.ins;
147
 
        break;
148
 
    case AGNODE:
149
 
        fn = cbstack->f->node.ins;
150
 
        break;
151
 
    case AGEDGE:
152
 
        fn = cbstack->f->edge.ins;
153
 
        break;
154
 
    }
155
 
    if (fn)
156
 
        fn(obj, cbstack->state);
157
 
}
158
 
 
159
 
void agmethod_upd(Agraph_t * g, void *obj, Agsym_t * sym)
160
 
{
161
 
    if (g->clos->callbacks_enabled)
162
 
        agupdcb(obj, sym, g->clos->cb);
163
 
    else
164
 
        agrecord_callback(obj, CB_UPDATE, sym);
165
 
}
166
 
 
167
 
void agupdcb(void *obj, Agsym_t * sym, Agcbstack_t * cbstack)
168
 
{
169
 
    agobjupdfn_t fn;
170
 
 
171
 
    if (cbstack == NIL(Agcbstack_t *))
172
 
        return;
173
 
    agupdcb(obj, sym, cbstack->prev);
174
 
    fn = NIL(agobjupdfn_t);
175
 
    switch (AGTYPE(obj)) {
176
 
    case AGRAPH:
177
 
        fn = cbstack->f->graph.mod;
178
 
        break;
179
 
    case AGNODE:
180
 
        fn = cbstack->f->node.mod;
181
 
        break;
182
 
    case AGEDGE:
183
 
        fn = cbstack->f->edge.mod;
184
 
        break;
185
 
    }
186
 
    if (fn)
187
 
        fn(obj, cbstack->state, sym);
188
 
}
189
 
 
190
 
void agmethod_delete(Agraph_t * g, void *obj)
191
 
{
192
 
    if (g->clos->callbacks_enabled)
193
 
        agdelcb(obj, g->clos->cb);
194
 
    else
195
 
        agrecord_callback(obj, CB_DELETION, NILsym);
196
 
}
197
 
 
198
 
void agdelcb(void *obj, Agcbstack_t * cbstack)
199
 
{
200
 
    agobjfn_t fn;
201
 
 
202
 
    if (cbstack == NIL(Agcbstack_t *))
203
 
        return;
204
 
    agdelcb(obj, cbstack->prev);
205
 
    fn = NIL(agobjfn_t);
206
 
    switch (AGTYPE(obj)) {
207
 
    case AGRAPH:
208
 
        fn = cbstack->f->graph.del;
209
 
        break;
210
 
    case AGNODE:
211
 
        fn = cbstack->f->node.del;
212
 
        break;
213
 
    case AGEDGE:
214
 
        fn = cbstack->f->edge.del;
215
 
        break;
216
 
    }
217
 
    if (fn)
218
 
        fn(obj, cbstack->state);
219
 
}
220
 
 
221
 
Agraph_t *agraphof(void *obj)
222
 
{
223
 
    switch (AGTYPE(obj)) {
224
 
    case AGINEDGE:
225
 
    case AGOUTEDGE:
226
 
        return ((Agedge_t *) obj)->node->g;
227
 
    case AGNODE:
228
 
        return ((Agnode_t *) obj)->g;
229
 
    case AGRAPH:
230
 
        return (Agraph_t *) obj;
231
 
    default:                    /* actually can't occur if only 2 bit tags */
232
 
        agerror(AGERROR_BADOBJ, "agraphof");
233
 
        return NILgraph;
234
 
    }
235
 
}
236
 
 
237
 
int agisarootobj(void *obj)
238
 
{
239
 
    return (agraphof(obj)->desc.maingraph);
240
 
}
241
 
 
242
 
/* to manage disciplines */
243
 
 
244
 
void agpushdisc(Agraph_t * g, Agcbdisc_t * cbd, void *state)
245
 
{
246
 
    Agcbstack_t *stack_ent;
247
 
 
248
 
    stack_ent = AGNEW(g, Agcbstack_t);
249
 
    stack_ent->f = cbd;
250
 
    stack_ent->state = state;
251
 
    stack_ent->prev = g->clos->cb;
252
 
    g->clos->cb = stack_ent;
253
 
}
254
 
 
255
 
int agpopdisc(Agraph_t * g, Agcbdisc_t * cbd)
256
 
{
257
 
    Agcbstack_t *stack_ent;
258
 
 
259
 
    stack_ent = g->clos->cb;
260
 
    if (stack_ent) {
261
 
        if (stack_ent->f == cbd)
262
 
            g->clos->cb = stack_ent->prev;
263
 
        else {
264
 
            while (stack_ent && (stack_ent->prev->f != cbd))
265
 
                stack_ent = stack_ent->prev;
266
 
            if (stack_ent && stack_ent->prev)
267
 
                stack_ent->prev = stack_ent->prev->prev;
268
 
        }
269
 
        if (stack_ent) {
270
 
            agfree(g, stack_ent);
271
 
            return SUCCESS;
272
 
        }
273
 
    }
274
 
    return FAILURE;
275
 
}
276
 
 
277
 
void *aggetuserptr(Agraph_t * g, Agcbdisc_t * cbd)
278
 
{
279
 
    Agcbstack_t *stack_ent;
280
 
 
281
 
    for (stack_ent = g->clos->cb; stack_ent; stack_ent = stack_ent->prev)
282
 
        if (stack_ent->f == cbd)
283
 
            return stack_ent->state;
284
 
    return NIL(void *);
285
 
}
286
 
 
287
 
Dtdisc_t Ag_obj_id_disc = {
288
 
    0,                          /* pass object ptr      */
289
 
    0,                          /* size (ignored)       */
290
 
    offsetof(Agobj_t, id_link), /* link offset */
291
 
    NIL(Dtmake_f),
292
 
    NIL(Dtfree_f),
293
 
    agobjidcmpf,
294
 
    NIL(Dthash_f),
295
 
    agdictobjmem,
296
 
    NIL(Dtevent_f)
297
 
};
298
 
 
299
 
Dtdisc_t Ag_obj_seq_disc = {
300
 
    0,                          /* pass object ptr      */
301
 
    0,                          /* size (ignored)       */
302
 
    offsetof(Agobj_t, seq_link),        /* link offset */
303
 
    NIL(Dtmake_f),
304
 
    NIL(Dtfree_f),
305
 
    agobjseqcmpf,
306
 
    NIL(Dthash_f),
307
 
    agdictobjmem,
308
 
    NIL(Dtevent_f)
309
 
};