Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/tools/jam/src/modules/order.c @ 29

Last change on this file since 29 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 4.0 KB
Line 
1/* Copyright Vladimir Prus 2004. Distributed under the Boost */
2/* Software License, Version 1.0. (See accompanying */
3/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
4
5#include "../native.h"
6#include "../lists.h"
7#include "../strings.h"
8#include "../newstr.h"
9#include "../variable.h"
10#include "../debug.h"
11
12
13/* Use quite klugy approach: when we add order dependency from 'a' to 'b',
14   just append 'b' to of value of variable 'a'.
15*/
16LIST *add_pair( PARSE *parse, FRAME *frame )
17{
18    LIST* arg = lol_get( frame->args, 0 );   
19
20    var_set(arg->string, list_copy(0, arg->next), VAR_APPEND);
21
22    return L0;
23}
24
25/** Given a list and a value, returns position of that value in
26    the list, or -1 if not found.
27*/
28int list_index(LIST* list, const char* value)
29{
30    int result = 0;
31    for(; list; list = list->next, ++result) {
32        if (strcmp(list->string, value) == 0)
33            return result;
34    }
35    return -1;
36}
37
38enum colors { white, gray, black };
39
40/* Main routite of topological sort. Calls itself recursively on all
41   adjacent vertices which were not yet visited. After that, 'current_vertex'
42   is added to '*result_ptr'.
43*/
44void do_ts(int** graph, int current_vertex, int* colors, int** result_ptr)
45{
46    int i;
47
48    colors[current_vertex] = gray;
49    for(i = 0; graph[current_vertex][i] != -1; ++i) {
50        int adjacent_vertex = graph[current_vertex][i];
51
52        if (colors[adjacent_vertex] == white)
53            do_ts(graph, adjacent_vertex, colors, result_ptr);
54        else if (colors[adjacent_vertex] == gray)
55            ; /* This is loop. Not sure what to do... */
56    }
57    colors[current_vertex] = black;
58    **result_ptr = current_vertex;   
59    (*result_ptr)++;
60}
61
62void topological_sort(int** graph, int num_vertices, int* result)
63{
64    int i;
65    int* colors = (int*)calloc(num_vertices, sizeof(int));
66    if ( DEBUG_PROFILE )
67        profile_memory( num_vertices*sizeof(int) );
68    for (i = 0; i < num_vertices; ++i)
69        colors[i] = white;
70
71    for(i = 0; i < num_vertices; ++i)
72        if (colors[i] == white)
73            do_ts(graph, i, colors, &result);
74
75    free(colors);
76}
77
78LIST *order( PARSE *parse, FRAME *frame )
79{
80    LIST* arg = lol_get( frame->args, 0 ); 
81    LIST* tmp;
82    LIST* result = 0;
83    int src, dst;
84
85    /* We need to create a graph of order dependencies between
86       the passed objects. We assume that there are no duplicates
87       passed to 'add_pair'.
88    */
89    int length = list_length(arg);
90    int** graph = (int**)calloc(length, sizeof(int*));
91    int* order = (int*)malloc((length+1)*sizeof(int));
92    if ( DEBUG_PROFILE )
93        profile_memory( length*sizeof(int*) + (length+1)*sizeof(int) );
94   
95    for(tmp = arg, src = 0; tmp; tmp = tmp->next, ++src) {
96        /* For all object this one depend upon, add elements
97           to 'graph' */
98        LIST* dependencies = var_get(tmp->string);
99        int index = 0;
100
101        graph[src] = (int*)calloc(list_length(dependencies)+1, sizeof(int));
102        if ( DEBUG_PROFILE )
103            profile_memory( (list_length(dependencies)+1)*sizeof(int) );
104        for(; dependencies; dependencies = dependencies->next) {         
105            int dst = list_index(arg, dependencies->string);
106            if (dst != -1)
107                graph[src][index++] = dst;
108        }
109        graph[src][index] = -1;               
110    }
111
112    topological_sort(graph, length, order);
113
114    {
115        int index = length-1;
116        for(; index >= 0; --index) {
117            int i;
118            tmp = arg;
119            for (i = 0; i < order[index]; ++i, tmp = tmp->next);
120            result = list_new(result, tmp->string);
121        }
122    }
123
124    /* Clean up */
125    {
126        int i;
127        for(i = 0; i < length; ++i)
128            free(graph[i]);
129        free(graph);
130        free(order);
131    }
132
133    return result;
134}
135
136void init_order()
137{
138    {
139        char* args[] = { "first", "second", 0 };
140        declare_native_rule("class@order", "add-pair", args, add_pair, 1);
141    }
142
143    {
144        char* args[] = { "objects", "*", 0 };
145        declare_native_rule("class@order", "order", args, order, 1);
146    }
147
148
149}
Note: See TracBrowser for help on using the repository browser.