tcldot-nodecmd.c 6.2 KB

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