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 */
19static 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
26static 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
33static 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 */
43static 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) */
61int 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