acyclic.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /**
  2. * @file
  3. * @brief make directed graph acyclic
  4. */
  5. /*************************************************************************
  6. * Copyright (c) 2011 AT&T Intellectual Property
  7. * All rights reserved. This program and the accompanying materials
  8. * are made available under the terms of the Eclipse Public License v1.0
  9. * which accompanies this distribution, and is available at
  10. * https://www.eclipse.org/legal/epl-v10.html
  11. *
  12. * Contributors: Details at https://graphviz.org
  13. *************************************************************************/
  14. /*
  15. * Written by Stephen North
  16. * Updated by Emden Gansner
  17. */
  18. #include <stdbool.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <cgraph/cgraph.h>
  22. #include "openFile.h"
  23. #include <util/exit.h>
  24. #include <util/prisize_t.h>
  25. #include <util/unreachable.h>
  26. #define graphName(g) (agnameof(g))
  27. #include <getopt.h>
  28. static FILE *inFile;
  29. typedef graphviz_acyclic_options_t opts_t;
  30. static char *cmd;
  31. static char *useString = "Usage: %s [-nv?] [-o outfile] <file>\n\
  32. -o <file> - put output in <file>\n\
  33. -n - do not output graph\n\
  34. -v - verbose\n\
  35. -? - print usage\n";
  36. static void usage(int v)
  37. {
  38. fprintf(stderr, useString, cmd);
  39. graphviz_exit(v);
  40. }
  41. static void init(opts_t *opts, int argc, char *argv[]) {
  42. int c;
  43. cmd = argv[0];
  44. opterr = 0;
  45. while ((c = getopt(argc, argv, ":vno:")) != -1)
  46. switch (c) {
  47. case 'o':
  48. if (opts->outFile != NULL)
  49. fclose(opts->outFile);
  50. opts->outFile = openFile(argv[0], optarg, "w");
  51. break;
  52. case 'n':
  53. opts->doWrite = false;
  54. break;
  55. case 'v':
  56. opts->Verbose = true;
  57. break;
  58. case '?':
  59. if (optopt == '?')
  60. usage(0);
  61. else {
  62. fprintf(stderr, "%s: option -%c unrecognized\n", cmd,
  63. optopt);
  64. usage(-1);
  65. }
  66. break;
  67. case ':':
  68. fprintf(stderr, "%s: missing argument for option -%c\n",
  69. cmd, optopt);
  70. usage(-1);
  71. break;
  72. default:
  73. UNREACHABLE();
  74. }
  75. if (optind < argc) {
  76. inFile = openFile(argv[0], argv[optind], "r");
  77. } else
  78. inFile = stdin;
  79. if (!opts->outFile)
  80. opts->outFile = stdout;
  81. }
  82. int main(int argc, char *argv[])
  83. {
  84. Agraph_t *g;
  85. int rv = 0;
  86. opts_t opts = {.doWrite = true};
  87. size_t num_rev = 0;
  88. init(&opts, argc, argv);
  89. if ((g = agread(inFile, NULL)) != NULL) {
  90. if (agisdirected (g)) {
  91. rv |= graphviz_acyclic(g, &opts, &num_rev);
  92. if (opts.Verbose) {
  93. if (rv)
  94. fprintf(stderr, "Graph \"%s\" has cycles; %" PRISIZE_T " reversed edges\n",
  95. graphName(g), num_rev);
  96. else
  97. fprintf(stderr, "Graph \"%s\" is acyclic\n", graphName(g));
  98. }
  99. } else {
  100. rv = -1;
  101. if (opts.Verbose)
  102. fprintf(stderr, "Graph \"%s\" is undirected\n", graphName(g));
  103. }
  104. graphviz_exit(rv);
  105. } else
  106. graphviz_exit(-1);
  107. }