1 | /* $Id$ $Revision$ */ |
2 | /* vim:set shiftwidth=4 ts=8: */ |
3 | |
4 | /************************************************************************* |
5 | * Copyright (c) 2011 AT&T Intellectual Property |
6 | * All rights reserved. This program and the accompanying materials |
7 | * are made available under the terms of the Eclipse Public License v1.0 |
8 | * which accompanies this distribution, and is available at |
9 | * http://www.eclipse.org/legal/epl-v10.html |
10 | * |
11 | * Contributors: See CVS logs. Details at http://www.graphviz.org/ |
12 | *************************************************************************/ |
13 | |
14 | #include <cghdr.h> |
15 | |
16 | /* The following functions take a graph and a template (node/edge/graph) |
17 | * and return the object representing the template within the local graph. |
18 | */ |
19 | static Agobj_t *subnode_search(Agraph_t * sub, Agobj_t * n) |
20 | { |
21 | if (agraphof(n) == sub) |
22 | return n; |
23 | return (Agobj_t *) agsubnode(sub, (Agnode_t *) n, FALSE); |
24 | } |
25 | |
26 | static Agobj_t *subedge_search(Agraph_t * sub, Agobj_t * e) |
27 | { |
28 | if (agraphof(e) == sub) |
29 | return e; |
30 | return (Agobj_t *) agsubedge(sub, (Agedge_t *) e, FALSE); |
31 | } |
32 | |
33 | static Agobj_t *subgraph_search(Agraph_t * sub, Agobj_t * g) |
34 | { |
35 | NOTUSED(g); |
36 | return (Agobj_t *) sub; |
37 | } |
38 | |
39 | /* recursively apply objfn within the hierarchy of a graph. |
40 | * if obj is a node or edge, it and its images in every subg are visited. |
41 | * if obj is a graph, then it and its subgs are visited. |
42 | */ |
43 | static void rec_apply(Agraph_t * g, Agobj_t * obj, agobjfn_t fn, void *arg, |
44 | agobjsearchfn_t objsearch, int preorder) |
45 | { |
46 | Agraph_t *sub; |
47 | Agobj_t *subobj; |
48 | |
49 | if (preorder) |
50 | fn(g, obj, arg); |
51 | for (sub = agfstsubg(g); sub; sub = agnxtsubg(sub)) { |
52 | if ((subobj = objsearch(sub, obj))) |
53 | rec_apply(sub, subobj, fn, arg, objsearch, preorder); |
54 | } |
55 | if (NOT(preorder)) |
56 | fn(g, obj, arg); |
57 | } |
58 | |
59 | /* external entry point (this seems to be one of those ineffective |
60 | * comments censured in books on programming style) */ |
61 | int agapply(Agraph_t * g, Agobj_t * obj, agobjfn_t fn, void *arg, |
62 | int preorder) |
63 | { |
64 | Agobj_t *subobj; |
65 | |
66 | agobjsearchfn_t objsearch; |
67 | switch (AGTYPE(obj)) { |
68 | case AGRAPH: |
69 | objsearch = subgraph_search; |
70 | break; |
71 | case AGNODE: |
72 | objsearch = subnode_search; |
73 | break; |
74 | case AGOUTEDGE: |
75 | case AGINEDGE: |
76 | objsearch = subedge_search; |
77 | break; |
78 | default: |
79 | agerr(AGERR, "agapply: unknown object type %d\n" , AGTYPE(obj)); |
80 | return FAILURE; |
81 | break; |
82 | } |
83 | if ((subobj = objsearch(g, obj))) { |
84 | rec_apply(g, subobj, fn, arg, objsearch, preorder); |
85 | return SUCCESS; |
86 | } else |
87 | return FAILURE; |
88 | } |
89 | |