File: vtkTopologicalSort.cmake

package info (click to toggle)
vtk9 9.5.2%2Bdfsg4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 206,616 kB
  • sloc: cpp: 2,340,827; ansic: 327,116; python: 114,881; yacc: 4,104; java: 3,977; sh: 3,032; xml: 2,771; perl: 2,189; lex: 1,787; javascript: 1,261; makefile: 189; objc: 153; tcl: 59
file content (103 lines) | stat: -rw-r--r-- 3,882 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
# SPDX-FileCopyrightText: Copyright 2010 Kitware, Inc.
# SPDX-FileCopyrightText: Copyright 2007 Douglas Gregor <doug.gregor@gmail.com>
# SPDX-FileCopyrightText: Copyright 2007 Troy Straszheim
# SPDX-License-Identifier: BSL-1.0

# Perform a reverse topological sort on the given LIST.
#
#   vtk_topological_sort(my_list "MY_" "_EDGES")
#
# LIST is the name of a variable containing a list of elements to be
# sorted in reverse topological order. Each element in the list has a
# set of outgoing edges (for example, those other list elements that
# it depends on). In the resulting reverse topological ordering
# (written back into the variable named LIST), an element will come
# later in the list than any of the elements that can be reached by
# following its outgoing edges and the outgoing edges of any vertices
# they target, recursively. Thus, if the edges represent dependencies
# on build targets, for example, the reverse topological ordering is
# the order in which one would build those targets.
#
# For each element E in this list, the edges for E are contained in
# the variable named ${PREFIX}${E}${SUFFIX}. If no such variable
# exists, then it is assumed that there are no edges. For example, if
# my_list contains a, b, and c, one could provide a dependency graph
# using the following variables:
#
#     MY_a_EDGES     b
#     MY_b_EDGES
#     MY_c_EDGES     a b
#
#  With the invocation of vtk_topological_sort shown above and these
#  variables, the resulting reverse topological ordering will be b, a,
#  c.
function(vtk_topological_sort LIST PREFIX SUFFIX)
  # Clear the stack and output variable
  set(VERTICES "${${LIST}}")
  set(STACK)
  set(${LIST})

  # Loop over all of the vertices, starting the topological sort from
  # each one.
  foreach(VERTEX IN LISTS VERTICES)

    # If we haven't already processed this vertex, start a depth-first
    # search from where.
    if (NOT FOUND_${VERTEX})
      # Push this vertex onto the stack with all of its outgoing edges
      string(REPLACE ";" " " NEW_ELEMENT
        "${VERTEX};${${PREFIX}${VERTEX}${SUFFIX}}")
      list(APPEND STACK "${NEW_ELEMENT}")

      # We've now seen this vertex
      set("FOUND_${VERTEX}" TRUE)

      # While the depth-first search stack is not empty
      while(STACK)
        # Remove the vertex and its remaining out-edges from the top
        # of the stack
        list(GET STACK -1 OUT_EDGES)
        list(REMOVE_AT STACK -1)

        # Get the source vertex and the list of out-edges
        separate_arguments(OUT_EDGES)
        list(GET OUT_EDGES 0 SOURCE)
        list(REMOVE_AT OUT_EDGES 0)

        # While there are still out-edges remaining
        while (OUT_EDGES)
          # Pull off the first outgoing edge
          list(GET OUT_EDGES 0 TARGET)
          list(REMOVE_AT OUT_EDGES 0)

          if (NOT FOUND_${TARGET})
            # We have not seen the target before, so we will traverse
            # its outgoing edges before coming back to our
            # source. This is the key to the depth-first traversal.

            # We've now seen this vertex
            set("FOUND_${TARGET}" TRUE)

            # Push the remaining edges for the current vertex onto the
            # stack
            string(REPLACE ";" " " NEW_ELEMENT
              "${SOURCE};${OUT_EDGES}")
            list(APPEND STACK "${NEW_ELEMENT}")

            # Setup the new source and outgoing edges
            set(SOURCE "${TARGET}")
            set(OUT_EDGES
              "${${PREFIX}${SOURCE}${SUFFIX}}")
          endif()
        endwhile ()

        # We have finished all of the outgoing edges for
        # SOURCE; add it to the resulting list.
        list(APPEND ${LIST} ${SOURCE})
      endwhile()
    endif ()
  endforeach()

  set("${LIST}" "${${LIST}}" PARENT_SCOPE)
endfunction()