Graphviz 13.0.0~dev.20250424.1043
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 "../tcl-compat.h"
12#include "tcldot.h"
13#include <stdlib.h>
14#include <string.h>
15#include <util/streq.h>
16
17static int nodecmd_internal(ClientData clientData, Tcl_Interp *interp, int argc,
18 char *argv[]) {
19 const char **argv2;
20 int i;
21 Agraph_t *g;
22 Agnode_t *n, *head;
23 Agedge_t *e;
24 Agsym_t *a;
25 gctx_t *gctx = (gctx_t *)clientData;
26
27 if (argc < 2) {
28 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
29 " option ?arg arg ...?\"", NULL);
30 return TCL_ERROR;
31 }
32 n = cmd2n(argv[0]);
33 if (!n) {
34 Tcl_AppendResult(interp, "node \"", argv[0], "\" not found", NULL);
35 return TCL_ERROR;
36 }
37 g = agraphof(n);
38
39 if (streq("addedge", argv[1])) {
40 if ((argc < 3) || (!(argc % 2))) {
41 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
42 " addedge head ?attributename attributevalue? ?...?\"",
43 NULL);
44 return TCL_ERROR;
45 }
46 head = cmd2n(argv[2]);
47 if (!head) {
48 if (!(head = agfindnode(g, argv[2]))) {
49 Tcl_AppendResult(interp, "head node \"", argv[2], "\" not found.",
50 NULL);
51 return TCL_ERROR;
52 }
53 }
54 if (agroot(g) != agroot(agraphof(head))) {
55 Tcl_AppendResult(interp, "nodes ", argv[0], " and ", argv[2],
56 " are not in the same graph.", NULL);
57 return TCL_ERROR;
58 }
59 e = agedge(g, n, head, NULL, 1);
60 Tcl_AppendResult(interp, obj2cmd(e), NULL);
61 setedgeattributes(agroot(g), e, &argv[3], (Tcl_Size)argc - 3);
62 return TCL_OK;
63
64 } else if (streq("delete", argv[1])) {
65 deleteNode(gctx, g, n);
66 return TCL_OK;
67
68 } else if (streq("findedge", argv[1])) {
69 if (argc < 3) {
70 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
71 " findedge headnodename\"", NULL);
72 return TCL_ERROR;
73 }
74 if (!(head = agfindnode(g, argv[2]))) {
75 Tcl_AppendResult(interp, "head node \"", argv[2], "\" not found.", NULL);
76 return TCL_ERROR;
77 }
78 if (!(e = agfindedge(g, n, head))) {
79 Tcl_AppendResult(interp, "edge \"", argv[0], " - ", obj2cmd(head),
80 "\" not found.", NULL);
81 return TCL_ERROR;
82 }
83 Tcl_AppendElement(interp, obj2cmd(head));
84 return TCL_OK;
85
86 } else if (streq("listattributes", argv[1])) {
87 listNodeAttrs(interp, g);
88 return TCL_OK;
89
90 } else if (streq("listedges", argv[1])) {
91 for (e = agfstedge(g, n); e; e = agnxtedge(g, e, n)) {
92 Tcl_AppendElement(interp, obj2cmd(e));
93 }
94 return TCL_OK;
95
96 } else if (streq("listinedges", argv[1])) {
97 for (e = agfstin(g, n); e; e = agnxtin(g, e)) {
98 Tcl_AppendElement(interp, obj2cmd(e));
99 }
100 return TCL_OK;
101
102 } else if (streq("listoutedges", argv[1])) {
103 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
104 Tcl_AppendElement(interp, obj2cmd(e));
105 }
106 return TCL_OK;
107
108 } else if (streq("queryattributes", argv[1])) {
109 for (i = 2; i < argc; i++) {
110 Tcl_Size argc2;
111 if (Tcl_SplitList(interp, argv[i], &argc2, &argv2) != TCL_OK)
112 return TCL_ERROR;
113 for (Tcl_Size j = 0; j < argc2; j++) {
114 char *arg = strdup(argv2[j]);
115 if ((a = agfindnodeattr(g, arg))) {
116 Tcl_AppendElement(interp, agxget(n, a));
117 } else {
118 Tcl_AppendResult(interp, "no attribute named \"", arg, "\"", NULL);
119 free(arg);
120 Tcl_Free((char *)argv2);
121 return TCL_ERROR;
122 }
123 free(arg);
124 }
125 Tcl_Free((char *)argv2);
126 }
127 return TCL_OK;
128
129 } else if (streq("queryattributevalues", argv[1])) {
130 for (i = 2; i < argc; i++) {
131 Tcl_Size argc2;
132 if (Tcl_SplitList(interp, argv[i], &argc2, &argv2) != TCL_OK)
133 return TCL_ERROR;
134 for (Tcl_Size j = 0; j < argc2; j++) {
135 char *arg = strdup(argv2[j]);
136 if ((a = agfindnodeattr(g, arg))) {
137 Tcl_AppendElement(interp, arg);
138 Tcl_AppendElement(interp, agxget(n, a));
139 } else {
140 Tcl_AppendResult(interp, "no attribute named \"", arg, "\"", NULL);
141 free(arg);
142 Tcl_Free((char *)argv2);
143 return TCL_ERROR;
144 }
145 free(arg);
146 }
147 Tcl_Free((char *)argv2);
148 }
149 return TCL_OK;
150
151 } else if (streq("setattributes", argv[1])) {
152 g = agroot(g);
153 if (argc == 3) {
154 Tcl_Size argc2;
155 if (Tcl_SplitList(interp, argv[2], &argc2, &argv2) != TCL_OK)
156 return TCL_ERROR;
157 if ((argc2 == 0) || (argc2 % 2)) {
158 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
159 "\" setattributes attributename attributevalue "
160 "?attributename attributevalue? ?...?",
161 NULL);
162 Tcl_Free((char *)argv2);
163 return TCL_ERROR;
164 }
165 char **argv2_copy = tcldot_argv_dup(argc2, argv2);
166 setnodeattributes(g, n, argv2_copy, argc2);
167 tcldot_argv_free(argc2, argv2_copy);
168 Tcl_Free((char *)argv2);
169 } else {
170 if ((argc < 4) || (argc % 2)) {
171 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
172 "\" setattributes attributename attributevalue "
173 "?attributename attributevalue? ?...?",
174 NULL);
175 return TCL_ERROR;
176 }
177 setnodeattributes(g, n, &argv[2], (Tcl_Size)argc - 2);
178 }
179 return TCL_OK;
180
181 } else if (streq("showname", argv[1])) {
182 Tcl_SetResult(interp, agnameof(n), TCL_STATIC);
183 return TCL_OK;
184
185 } else {
186 Tcl_AppendResult(interp, "bad option \"", argv[1], "\": must be one of:",
187 "\n\taddedge, listattributes, listedges, listinedges,",
188 "\n\tlistoutedges, queryattributes, queryattributevalues,",
189 "\n\tsetattributes, showname.", NULL);
190 return TCL_ERROR;
191 }
192}
193
194int nodecmd(ClientData clientData, Tcl_Interp *interp, int argc,
195 const char *argv[]) {
196 char **argv_copy = tcldot_argv_dup(argc, argv);
197 int rc = nodecmd_internal(clientData, interp, argc, argv_copy);
198 tcldot_argv_free(argc, argv_copy);
199 return rc;
200}
#define head
Definition dthdr.h:15
void free(void *)
node NULL
Definition grammar.y:163
char * agxget(void *obj, Agsym_t *sym)
Definition attr.c:482
Agedge_t * agedge(Agraph_t *g, Agnode_t *t, Agnode_t *h, char *name, int createflag)
Definition edge.c:256
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:143
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:424
string attribute descriptor symbol in Agattr_s.dict
Definition cgraph.h:651
#define Tcl_Size
Definition tcl-compat.h:33
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)
Definition tcldot-util.c:99
char * obj2cmd(void *obj)
Definition tcldot-util.c:64
void setnodeattributes(Agraph_t *g, Agnode_t *n, char *argv[], Tcl_Size argc)
void setedgeattributes(Agraph_t *g, Agedge_t *e, char *argv[], Tcl_Size 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:46