Graphviz 13.0.0~dev.20241220.2304
Loading...
Searching...
No Matches
tcldot-nodecmd.c
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11#include "tcldot.h"
12#include <string.h>
13#include <util/streq.h>
14
15static int nodecmd_internal(ClientData clientData, Tcl_Interp *interp, int argc,
16 char *argv[]) {
17 char **argv2;
18 int i, j, argc2;
19 Agraph_t *g;
20 Agnode_t *n, *head;
21 Agedge_t *e;
22 Agsym_t *a;
23 gctx_t *gctx = (gctx_t *)clientData;
24
25 if (argc < 2) {
26 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
27 " option ?arg arg ...?\"", NULL);
28 return TCL_ERROR;
29 }
30 n = cmd2n(argv[0]);
31 if (!n) {
32 Tcl_AppendResult(interp, "node \"", argv[0], "\" not found", NULL);
33 return TCL_ERROR;
34 }
35 g = agraphof(n);
36
37 if (streq("addedge", argv[1])) {
38 if ((argc < 3) || (!(argc % 2))) {
39 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
40 " addedge head ?attributename attributevalue? ?...?\"",
41 NULL);
42 return TCL_ERROR;
43 }
44 head = cmd2n(argv[2]);
45 if (!head) {
46 if (!(head = agfindnode(g, argv[2]))) {
47 Tcl_AppendResult(interp, "head node \"", argv[2], "\" not found.",
48 NULL);
49 return TCL_ERROR;
50 }
51 }
52 if (agroot(g) != agroot(agraphof(head))) {
53 Tcl_AppendResult(interp, "nodes ", argv[0], " and ", argv[2],
54 " are not in the same graph.", NULL);
55 return TCL_ERROR;
56 }
57 e = agedge(g, n, head, NULL, 1);
58 Tcl_AppendResult(interp, obj2cmd(e), NULL);
59 setedgeattributes(agroot(g), e, &argv[3], argc - 3);
60 return TCL_OK;
61
62 } else if (streq("delete", argv[1])) {
63 deleteNode(gctx, g, n);
64 return TCL_OK;
65
66 } else if (streq("findedge", argv[1])) {
67 if (argc < 3) {
68 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
69 " findedge headnodename\"", NULL);
70 return TCL_ERROR;
71 }
72 if (!(head = agfindnode(g, argv[2]))) {
73 Tcl_AppendResult(interp, "head node \"", argv[2], "\" not found.", NULL);
74 return TCL_ERROR;
75 }
76 if (!(e = agfindedge(g, n, head))) {
77 Tcl_AppendResult(interp, "edge \"", argv[0], " - ", obj2cmd(head),
78 "\" not found.", NULL);
79 return TCL_ERROR;
80 }
81 Tcl_AppendElement(interp, obj2cmd(head));
82 return TCL_OK;
83
84 } else if (streq("listattributes", argv[1])) {
85 listNodeAttrs(interp, g);
86 return TCL_OK;
87
88 } else if (streq("listedges", argv[1])) {
89 for (e = agfstedge(g, n); e; e = agnxtedge(g, e, n)) {
90 Tcl_AppendElement(interp, obj2cmd(e));
91 }
92 return TCL_OK;
93
94 } else if (streq("listinedges", argv[1])) {
95 for (e = agfstin(g, n); e; e = agnxtin(g, e)) {
96 Tcl_AppendElement(interp, obj2cmd(e));
97 }
98 return TCL_OK;
99
100 } else if (streq("listoutedges", argv[1])) {
101 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
102 Tcl_AppendElement(interp, obj2cmd(e));
103 }
104 return TCL_OK;
105
106 } else if (streq("queryattributes", argv[1])) {
107 for (i = 2; i < argc; i++) {
108 if (Tcl_SplitList(interp, argv[i], &argc2, (const char ***)&argv2) !=
109 TCL_OK)
110 return TCL_ERROR;
111 for (j = 0; j < argc2; j++) {
112 if ((a = agfindnodeattr(g, argv2[j]))) {
113 Tcl_AppendElement(interp, agxget(n, a));
114 } else {
115 Tcl_AppendResult(interp, "no attribute named \"", argv2[j], "\"",
116 NULL);
117 Tcl_Free((char *)argv2);
118 return TCL_ERROR;
119 }
120 }
121 Tcl_Free((char *)argv2);
122 }
123 return TCL_OK;
124
125 } else if (streq("queryattributevalues", argv[1])) {
126 for (i = 2; i < argc; i++) {
127 if (Tcl_SplitList(interp, argv[i], &argc2, (const char ***)&argv2) !=
128 TCL_OK)
129 return TCL_ERROR;
130 for (j = 0; j < argc2; j++) {
131 if ((a = agfindnodeattr(g, argv2[j]))) {
132 Tcl_AppendElement(interp, argv2[j]);
133 Tcl_AppendElement(interp, agxget(n, a));
134 } else {
135 Tcl_AppendResult(interp, "no attribute named \"", argv2[j], "\"",
136 NULL);
137 Tcl_Free((char *)argv2);
138 return TCL_ERROR;
139 }
140 }
141 Tcl_Free((char *)argv2);
142 }
143 return TCL_OK;
144
145 } else if (streq("setattributes", argv[1])) {
146 g = agroot(g);
147 if (argc == 3) {
148 if (Tcl_SplitList(interp, argv[2], &argc2, (const char ***)&argv2) !=
149 TCL_OK)
150 return TCL_ERROR;
151 if ((argc2 == 0) || (argc2 % 2)) {
152 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
153 "\" setattributes attributename attributevalue "
154 "?attributename attributevalue? ?...?",
155 NULL);
156 Tcl_Free((char *)argv2);
157 return TCL_ERROR;
158 }
159 setnodeattributes(g, n, argv2, argc2);
160 Tcl_Free((char *)argv2);
161 } else {
162 if ((argc < 4) || (argc % 2)) {
163 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
164 "\" setattributes attributename attributevalue "
165 "?attributename attributevalue? ?...?",
166 NULL);
167 return TCL_ERROR;
168 }
169 setnodeattributes(g, n, &argv[2], argc - 2);
170 }
171 return TCL_OK;
172
173 } else if (streq("showname", argv[1])) {
174 Tcl_SetResult(interp, agnameof(n), TCL_STATIC);
175 return TCL_OK;
176
177 } else {
178 Tcl_AppendResult(interp, "bad option \"", argv[1], "\": must be one of:",
179 "\n\taddedge, listattributes, listedges, listinedges,",
180 "\n\tlistoutedges, queryattributes, queryattributevalues,",
181 "\n\tsetattributes, showname.", NULL);
182 return TCL_ERROR;
183 }
184}
185
186int nodecmd(ClientData clientData, Tcl_Interp *interp, int argc,
187 const char *argv[]) {
188 char **argv_copy = tcldot_argv_dup(argc, argv);
189 int rc = nodecmd_internal(clientData, interp, argc, argv_copy);
190 tcldot_argv_free(argc, argv_copy);
191 return rc;
192}
#define head
Definition dthdr.h:15
node NULL
Definition grammar.y:163
char * agxget(void *obj, Agsym_t *sym)
Definition attr.c:455
Agedge_t * agedge(Agraph_t *g, Agnode_t *t, Agnode_t *h, char *name, int createflag)
Definition edge.c:260
Agedge_t * agnxtin(Agraph_t *g, Agedge_t *e)
Definition edge.c:69
Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Definition edge.c:24
#define agfindedge(g, t, h)
Definition types.h:609
Agedge_t * agnxtedge(Agraph_t *g, Agedge_t *e, Agnode_t *n)
Definition edge.c:94
Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
Definition edge.c:39
Agedge_t * agfstedge(Agraph_t *g, Agnode_t *n)
Definition edge.c:85
Agedge_t * agfstin(Agraph_t *g, Agnode_t *n)
Definition edge.c:55
#define agfindnodeattr(g, a)
Definition types.h:615
#define agfindnode(g, n)
Definition types.h:611
Agraph_t * agraphof(void *obj)
Definition obj.c:185
char * agnameof(void *)
returns a string descriptor for the object.
Definition id.c:158
Agraph_t * agroot(void *obj)
Definition obj.c:168
static bool streq(const char *a, const char *b)
are a and b equal?
Definition streq.h:11
graph or subgraph
Definition cgraph.h:425
string attribute descriptor symbol in Agattr_s.dict
Definition cgraph.h:637
static int nodecmd_internal(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
int nodecmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[])
void listNodeAttrs(Tcl_Interp *interp, Agraph_t *g)
void deleteNode(gctx_t *gctx, Agraph_t *g, Agnode_t *n)
char * obj2cmd(void *obj)
Definition tcldot-util.c:66
void setnodeattributes(Agraph_t *g, Agnode_t *n, char *argv[], int argc)
void setedgeattributes(Agraph_t *g, Agedge_t *e, char *argv[], int argc)
void tcldot_argv_free(int argc, char *argv[])
free the strings pointed to by argv
char ** tcldot_argv_dup(int argc, const char *argv[])
duplicate the strings pointed to by argv as non-const strings
Agnode_t * cmd2n(const char *cmd)
Definition tcldot-util.c:48