line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#include "EXTERN.h"
|
2
|
|
|
|
|
|
|
#include "perl.h"
|
3
|
|
|
|
|
|
|
#include "XSUB.h"
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
#include "ppport.h"
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
#define isPenalty(sv) (SvROK(sv) && sv_derived_from(sv, "Text::KnuthPlass::Penalty"))
|
8
|
|
|
|
|
|
|
#define ivHash(hv, key) (IV)SvIV(*hv_fetch((HV*)hv, key, strlen(key), TRUE))
|
9
|
|
|
|
|
|
|
#define nvHash(hv, key) (NV)SvNVx(*hv_fetch((HV*)hv, key, strlen(key), TRUE))
|
10
|
|
|
|
|
|
|
#define debug(x)
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
typedef SV * Text_KnuthPlass;
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
struct Breakpoint_s {
|
15
|
|
|
|
|
|
|
struct Breakpoint_s * prev;
|
16
|
|
|
|
|
|
|
struct Breakpoint_s * next;
|
17
|
|
|
|
|
|
|
struct Breakpoint_s * previous;
|
18
|
|
|
|
|
|
|
struct Breakpoint_s * active; /* Just for candidates */
|
19
|
|
|
|
|
|
|
NV demerits;
|
20
|
|
|
|
|
|
|
NV ratio;
|
21
|
|
|
|
|
|
|
IV line;
|
22
|
|
|
|
|
|
|
IV position;
|
23
|
|
|
|
|
|
|
IV fitness_class;
|
24
|
|
|
|
|
|
|
HV* totals;
|
25
|
|
|
|
|
|
|
};
|
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
typedef struct Breakpoint_s Breakpoint;
|
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
typedef struct LinkedList_s {
|
30
|
|
|
|
|
|
|
Breakpoint* head;
|
31
|
|
|
|
|
|
|
Breakpoint* tail;
|
32
|
|
|
|
|
|
|
IV list_size;
|
33
|
|
|
|
|
|
|
AV* to_free;
|
34
|
|
|
|
|
|
|
} LinkedList;
|
35
|
|
|
|
|
|
|
|
36
|
1364
|
|
|
|
|
|
NV _compute_cost(Text_KnuthPlass self, IV start, IV end, Breakpoint* a,
|
37
|
|
|
|
|
|
|
IV current_line, AV* nodes) {
|
38
|
1364
|
50
|
|
|
|
|
IV infinity = ivHash(self, "infinity");
|
39
|
1364
|
|
|
|
|
|
HV* sum = (HV*)SvRV(*hv_fetch((HV*)self, "sum", 3, FALSE));
|
40
|
1364
|
|
|
|
|
|
HV* totals = a->totals;
|
41
|
1364
|
100
|
|
|
|
|
NV width = nvHash(sum, "width") - nvHash(totals,"width");
|
|
|
50
|
|
|
|
|
|
42
|
1364
|
|
|
|
|
|
AV* linelengths = (AV*)SvRV(*hv_fetch((HV*)self, "linelengths", 11, FALSE));
|
43
|
1364
|
|
|
|
|
|
I32 ll = av_len(linelengths);
|
44
|
|
|
|
|
|
|
NV stretch = 0;
|
45
|
|
|
|
|
|
|
NV shrink = 0;
|
46
|
1364
|
50
|
|
|
|
|
NV linelength = SvNV(*av_fetch(linelengths, current_line <= ll ? current_line-1 : ll, 0));
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
debug(warn("Computing cost from %i to %i\n", start, end));
|
49
|
|
|
|
|
|
|
debug(warn("Sum width: %f\n", nvHash(sum, "width")));
|
50
|
|
|
|
|
|
|
debug(warn("Total width: %f\n", nvHash(totals, "width")));
|
51
|
1364
|
50
|
|
|
|
|
if (isPenalty(*av_fetch(nodes, end, 0))) {
|
|
|
100
|
|
|
|
|
|
52
|
|
|
|
|
|
|
debug(warn("Adding penalty width\n"));
|
53
|
394
|
100
|
|
|
|
|
width += nvHash(SvRV(*av_fetch(nodes,end, 0)),"width");
|
54
|
|
|
|
|
|
|
}
|
55
|
|
|
|
|
|
|
debug(warn("Width %f, linelength %f\n", width, linelength));
|
56
|
1364
|
100
|
|
|
|
|
if (width < linelength) {
|
57
|
1316
|
100
|
|
|
|
|
stretch = nvHash(sum, "stretch") - nvHash(totals, "stretch");
|
|
|
50
|
|
|
|
|
|
58
|
|
|
|
|
|
|
debug(warn("Stretch %f\n", stretch));
|
59
|
1316
|
100
|
|
|
|
|
if (stretch > 0) {
|
60
|
1104
|
|
|
|
|
|
return (linelength - width) / stretch;
|
61
|
|
|
|
|
|
|
} else {
|
62
|
212
|
|
|
|
|
|
return infinity;
|
63
|
|
|
|
|
|
|
}
|
64
|
48
|
100
|
|
|
|
|
} else if (width > linelength) {
|
65
|
|
|
|
|
|
|
debug(warn("Shrink %f\n", shrink));
|
66
|
25
|
50
|
|
|
|
|
shrink = nvHash(sum, "shrink") - nvHash(totals, "shrink");
|
|
|
50
|
|
|
|
|
|
67
|
25
|
50
|
|
|
|
|
if (shrink > 0) {
|
68
|
25
|
|
|
|
|
|
return (linelength - width) / shrink;
|
69
|
|
|
|
|
|
|
} else {
|
70
|
0
|
|
|
|
|
|
return infinity;
|
71
|
|
|
|
|
|
|
}
|
72
|
|
|
|
|
|
|
} else { return 0; }
|
73
|
|
|
|
|
|
|
}
|
74
|
|
|
|
|
|
|
|
75
|
157
|
|
|
|
|
|
HV* _compute_sum(Text_KnuthPlass self, IV index, AV* nodes) {
|
76
|
157
|
|
|
|
|
|
HV* result = newHV();
|
77
|
157
|
|
|
|
|
|
HV* sum = (HV*)SvRV(*hv_fetch((HV*)self, "sum", 3, FALSE));
|
78
|
157
|
50
|
|
|
|
|
IV infinity = ivHash(self, "infinity");
|
79
|
157
|
50
|
|
|
|
|
NV width = nvHash(sum, "width");
|
80
|
157
|
50
|
|
|
|
|
NV stretch = nvHash(sum, "stretch");
|
81
|
157
|
50
|
|
|
|
|
NV shrink = nvHash(sum, "shrink");
|
82
|
157
|
|
|
|
|
|
I32 len = av_len(nodes);
|
83
|
157
|
|
|
|
|
|
I32 i = index;
|
84
|
|
|
|
|
|
|
|
85
|
311
|
100
|
|
|
|
|
while (i < len) {
|
86
|
304
|
|
|
|
|
|
SV* e = *av_fetch(nodes, i, 0);
|
87
|
304
|
100
|
|
|
|
|
if (sv_derived_from(e, "Text::KnuthPlass::Glue")) {
|
88
|
122
|
100
|
|
|
|
|
width += nvHash(SvRV(e), "width");
|
89
|
122
|
100
|
|
|
|
|
stretch += nvHash(SvRV(e), "stretch");
|
90
|
122
|
100
|
|
|
|
|
shrink += nvHash(SvRV(e), "shrink");
|
91
|
182
|
100
|
|
|
|
|
} else if (sv_derived_from(e, "Text::KnuthPlass::Box") ||
|
|
|
50
|
|
|
|
|
|
92
|
32
|
50
|
|
|
|
|
(isPenalty(e) && ivHash(SvRV(e), "penalty") == -infinity
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
93
|
0
|
0
|
|
|
|
|
&& i > index)) {
|
94
|
|
|
|
|
|
|
break;
|
95
|
|
|
|
|
|
|
}
|
96
|
154
|
|
|
|
|
|
i++;
|
97
|
|
|
|
|
|
|
}
|
98
|
|
|
|
|
|
|
|
99
|
157
|
|
|
|
|
|
hv_stores(result, "width", newSVnv(width));
|
100
|
157
|
|
|
|
|
|
hv_stores(result, "stretch", newSVnv(stretch));
|
101
|
157
|
|
|
|
|
|
hv_stores(result, "shrink", newSVnv(shrink));
|
102
|
157
|
|
|
|
|
|
return result;
|
103
|
|
|
|
|
|
|
}
|
104
|
|
|
|
|
|
|
|
105
|
317
|
|
|
|
|
|
Breakpoint* _new_breakpoint (void) {
|
106
|
|
|
|
|
|
|
Breakpoint* dummy;
|
107
|
317
|
|
|
|
|
|
HV* totals = newHV();
|
108
|
317
|
|
|
|
|
|
Newxz(dummy, 1, Breakpoint);
|
109
|
317
|
|
|
|
|
|
dummy->prev = dummy->next = dummy->previous = dummy->active = NULL;
|
110
|
317
|
|
|
|
|
|
dummy->demerits = dummy->ratio = 0;
|
111
|
317
|
|
|
|
|
|
dummy->line = dummy->position = dummy->fitness_class = 0;
|
112
|
317
|
|
|
|
|
|
hv_stores(totals, "width", newSVnv(0));
|
113
|
317
|
|
|
|
|
|
hv_stores(totals, "stretch", newSVnv(0));
|
114
|
317
|
|
|
|
|
|
hv_stores(totals, "shrink", newSVnv(0));
|
115
|
317
|
|
|
|
|
|
dummy->totals = totals;
|
116
|
317
|
|
|
|
|
|
return dummy;
|
117
|
|
|
|
|
|
|
}
|
118
|
|
|
|
|
|
|
|
119
|
0
|
|
|
|
|
|
void free_breakpoint(Breakpoint* b) {
|
120
|
0
|
0
|
|
|
|
|
while (b) {
|
121
|
0
|
|
|
|
|
|
Breakpoint* p = b->previous;
|
122
|
0
|
0
|
|
|
|
|
if (SvROK(b->totals)) {
|
123
|
0
|
|
|
|
|
|
sv_free((SV*)b->totals);
|
124
|
0
|
|
|
|
|
|
Safefree(b);
|
125
|
|
|
|
|
|
|
}
|
126
|
|
|
|
|
|
|
b = p;
|
127
|
|
|
|
|
|
|
}
|
128
|
0
|
0
|
|
|
|
|
if (b && b->totals) sv_free((SV*)b->totals);
|
|
|
0
|
|
|
|
|
|
129
|
0
|
0
|
|
|
|
|
if (b) Safefree(b);
|
130
|
0
|
|
|
|
|
|
}
|
131
|
|
|
|
|
|
|
|
132
|
157
|
|
|
|
|
|
void _unlinkKP(LinkedList* list, Breakpoint* a) {
|
133
|
157
|
100
|
|
|
|
|
if (!a->prev) { list->head = a->next; } else { a->prev->next = a->next; }
|
134
|
157
|
100
|
|
|
|
|
if (!a->next) { list->tail = a->prev; } else { a->next->prev = a->prev; }
|
135
|
157
|
|
|
|
|
|
list->list_size--;
|
136
|
157
|
|
|
|
|
|
av_push(list->to_free, newSViv((IV)a));
|
137
|
157
|
|
|
|
|
|
}
|
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
MODULE = Text::KnuthPlass PACKAGE = Text::KnuthPlass
|
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
void
|
142
|
|
|
|
|
|
|
_init_nodelist(self)
|
143
|
|
|
|
|
|
|
Text_KnuthPlass self
|
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
CODE:
|
146
|
|
|
|
|
|
|
LinkedList* activelist;
|
147
|
3
|
|
|
|
|
|
Newxz(activelist, 1, LinkedList);
|
148
|
3
|
|
|
|
|
|
activelist->head = activelist->tail = _new_breakpoint();
|
149
|
3
|
|
|
|
|
|
activelist->list_size = 1;
|
150
|
3
|
|
|
|
|
|
activelist->to_free = newAV();
|
151
|
3
|
|
|
|
|
|
hv_stores((HV*)self, "activeNodes", ((IV)activelist));
|
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
void _active_to_breaks(self)
|
154
|
|
|
|
|
|
|
Text_KnuthPlass self
|
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
PREINIT:
|
157
|
|
|
|
|
|
|
LinkedList* activelist;
|
158
|
|
|
|
|
|
|
Breakpoint* b;
|
159
|
|
|
|
|
|
|
Breakpoint* best = NULL;
|
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
PPCODE:
|
162
|
3
|
|
|
|
|
|
activelist = (LinkedList*)(*hv_fetch((HV*)self, "activeNodes", 11, FALSE));
|
163
|
|
|
|
|
|
|
|
164
|
6
|
100
|
|
|
|
|
for (b = activelist->head; b; b = b->next) {
|
165
|
3
|
50
|
|
|
|
|
if (!best || b->demerits < best->demerits) best = b;
|
|
|
0
|
|
|
|
|
|
166
|
|
|
|
|
|
|
}
|
167
|
18
|
100
|
|
|
|
|
while (best) {
|
168
|
15
|
|
|
|
|
|
HV* posnode = newHV();
|
169
|
15
|
|
|
|
|
|
hv_stores(posnode, "position", newSViv(best->position));
|
170
|
15
|
|
|
|
|
|
hv_stores(posnode, "ratio", newSVnv(best->ratio));
|
171
|
15
|
50
|
|
|
|
|
XPUSHs(sv_2mortal(newRV((SV*)posnode)));
|
172
|
15
|
|
|
|
|
|
best = best->previous;
|
173
|
|
|
|
|
|
|
}
|
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
void _cleanup(self)
|
176
|
|
|
|
|
|
|
Text_KnuthPlass self
|
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
CODE:
|
179
|
|
|
|
|
|
|
Breakpoint* b;
|
180
|
|
|
|
|
|
|
LinkedList* activelist;
|
181
|
3
|
|
|
|
|
|
activelist = (LinkedList*)(*hv_fetch((HV*)self, "activeNodes", 11, FALSE));
|
182
|
|
|
|
|
|
|
return;
|
183
|
|
|
|
|
|
|
/* Free nodes on the activelist */
|
184
|
|
|
|
|
|
|
b = activelist->head;
|
185
|
|
|
|
|
|
|
while (b) {
|
186
|
|
|
|
|
|
|
Breakpoint* n = b->next;
|
187
|
|
|
|
|
|
|
free_breakpoint(b);
|
188
|
|
|
|
|
|
|
b = n;
|
189
|
|
|
|
|
|
|
}
|
190
|
|
|
|
|
|
|
/* Shut down the activelist itself */
|
191
|
|
|
|
|
|
|
while (av_len(activelist->to_free)) {
|
192
|
|
|
|
|
|
|
SV* pointer = av_shift(activelist->to_free);
|
193
|
|
|
|
|
|
|
if ((Breakpoint*)SvIV(pointer))
|
194
|
|
|
|
|
|
|
free_breakpoint((Breakpoint*)SvIV(pointer));
|
195
|
|
|
|
|
|
|
sv_free(pointer);
|
196
|
|
|
|
|
|
|
}
|
197
|
|
|
|
|
|
|
sv_free((SV*)activelist->to_free);
|
198
|
|
|
|
|
|
|
//Safefree(activelist);
|
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
void
|
201
|
|
|
|
|
|
|
_mainloop(self, node, index, nodes)
|
202
|
|
|
|
|
|
|
Text_KnuthPlass self
|
203
|
|
|
|
|
|
|
SV* node
|
204
|
|
|
|
|
|
|
IV index
|
205
|
|
|
|
|
|
|
AV* nodes
|
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
CODE:
|
208
|
102
|
|
|
|
|
|
LinkedList* activelist = (LinkedList*)(*hv_fetch((HV*)self, "activeNodes", 11, FALSE));
|
209
|
102
|
50
|
|
|
|
|
IV tolerance = ivHash(self, "tolerance");
|
210
|
102
|
50
|
|
|
|
|
IV infinity = ivHash(self, "infinity");
|
211
|
102
|
|
|
|
|
|
SV* demerits_r = *hv_fetch((HV*)self, "demerits", 8, FALSE);
|
212
|
|
|
|
|
|
|
NV ratio = 0;
|
213
|
|
|
|
|
|
|
IV nodepenalty = 0;
|
214
|
|
|
|
|
|
|
NV demerits = 0;
|
215
|
|
|
|
|
|
|
IV linedemerits = 0, flaggeddemerits = 0, fitnessdemerits = 0;
|
216
|
|
|
|
|
|
|
Breakpoint* candidates[4];
|
217
|
|
|
|
|
|
|
NV badness;
|
218
|
|
|
|
|
|
|
IV current_line = 0;
|
219
|
|
|
|
|
|
|
HV* tmpsum;
|
220
|
|
|
|
|
|
|
IV current_class = 0;
|
221
|
102
|
|
|
|
|
|
Breakpoint* active = activelist->head;
|
222
|
|
|
|
|
|
|
Breakpoint* next;
|
223
|
|
|
|
|
|
|
|
224
|
102
|
50
|
|
|
|
|
if (demerits_r && SvRV(demerits_r)) {
|
|
|
50
|
|
|
|
|
|
225
|
102
|
50
|
|
|
|
|
linedemerits = ivHash(SvRV(demerits_r), "line");
|
226
|
102
|
50
|
|
|
|
|
flaggeddemerits = ivHash(SvRV(demerits_r), "flagged");
|
227
|
102
|
50
|
|
|
|
|
fitnessdemerits = ivHash(SvRV(demerits_r), "fitness");
|
228
|
|
|
|
|
|
|
} else {
|
229
|
0
|
|
|
|
|
|
croak("Demerits hash not properly set!");
|
230
|
|
|
|
|
|
|
}
|
231
|
|
|
|
|
|
|
|
232
|
102
|
50
|
|
|
|
|
if (isPenalty(node)) {
|
|
|
100
|
|
|
|
|
|
233
|
21
|
50
|
|
|
|
|
nodepenalty = SvIV(*hv_fetch((HV*)SvRV(node), "penalty", 7, TRUE));
|
234
|
|
|
|
|
|
|
}
|
235
|
|
|
|
|
|
|
|
236
|
219
|
100
|
|
|
|
|
while (active) {
|
237
|
|
|
|
|
|
|
int t;
|
238
|
117
|
|
|
|
|
|
candidates[0] = NULL; candidates[1] = NULL;
|
239
|
117
|
|
|
|
|
|
candidates[2] = NULL; candidates[3] = NULL;
|
240
|
|
|
|
|
|
|
debug(warn("Outer\n"));
|
241
|
1364
|
50
|
|
|
|
|
while (active) {
|
242
|
1364
|
|
|
|
|
|
next = active->next;
|
243
|
1364
|
|
|
|
|
|
IV position = active->position;
|
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
debug(warn("Inner loop\n"));
|
246
|
|
|
|
|
|
|
|
247
|
1364
|
|
|
|
|
|
current_line = 1+ active->line;
|
248
|
1364
|
|
|
|
|
|
ratio = _compute_cost(self, position, index, active, current_line, nodes);
|
249
|
|
|
|
|
|
|
debug(warn("Got a ratio of %f\n", ratio));
|
250
|
1364
|
100
|
|
|
|
|
if (ratio < 1 || (isPenalty(node) && nodepenalty == -infinity))
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
251
|
157
|
|
|
|
|
|
_unlinkKP(activelist, active);
|
252
|
|
|
|
|
|
|
|
253
|
1364
|
100
|
|
|
|
|
if (-1 <= ratio && ratio <= tolerance) {
|
|
|
100
|
|
|
|
|
|
254
|
835
|
|
|
|
|
|
SV* nodeAtPos = *av_fetch(nodes, position, FALSE);
|
255
|
835
|
|
|
|
|
|
badness = 100 * ratio * ratio * ratio;
|
256
|
|
|
|
|
|
|
debug(warn("Badness is %f\n", badness));
|
257
|
835
|
50
|
|
|
|
|
if (isPenalty(node) && nodepenalty > 0) {
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
258
|
204
|
|
|
|
|
|
demerits = linedemerits + badness + nodepenalty;
|
259
|
631
|
50
|
|
|
|
|
} else if (isPenalty(node) && nodepenalty != -infinity) {
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
260
|
0
|
|
|
|
|
|
demerits = linedemerits + badness - nodepenalty;
|
261
|
|
|
|
|
|
|
} else {
|
262
|
631
|
|
|
|
|
|
demerits = linedemerits + badness;
|
263
|
|
|
|
|
|
|
}
|
264
|
835
|
|
|
|
|
|
demerits = demerits * demerits;
|
265
|
835
|
50
|
|
|
|
|
if (isPenalty(node) && isPenalty(SvRV(nodeAtPos))) {
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
266
|
0
|
|
|
|
|
|
demerits = demerits + (flaggeddemerits *
|
267
|
0
|
0
|
|
|
|
|
ivHash(node, "flagged") *
|
268
|
0
|
0
|
|
|
|
|
ivHash(SvRV(nodeAtPos), "flagged"));
|
269
|
|
|
|
|
|
|
}
|
270
|
|
|
|
|
|
|
|
271
|
835
|
100
|
|
|
|
|
if (ratio < -0.5) current_class = 0;
|
272
|
834
|
100
|
|
|
|
|
else if (ratio <= 0.5) current_class = 1;
|
273
|
724
|
100
|
|
|
|
|
else if (ratio <= 1) current_class = 2;
|
274
|
|
|
|
|
|
|
else current_class = 3;
|
275
|
|
|
|
|
|
|
|
276
|
835
|
100
|
|
|
|
|
if (abs(current_class - active->fitness_class) > 1)
|
277
|
242
|
|
|
|
|
|
demerits += fitnessdemerits;
|
278
|
|
|
|
|
|
|
|
279
|
835
|
|
|
|
|
|
demerits += active->demerits;
|
280
|
|
|
|
|
|
|
|
281
|
835
|
100
|
|
|
|
|
if (!candidates[current_class] ||
|
|
|
100
|
|
|
|
|
|
282
|
678
|
|
|
|
|
|
demerits < candidates[current_class]->demerits) {
|
283
|
|
|
|
|
|
|
debug(warn("Setting c %i\n", current_class));
|
284
|
295
|
100
|
|
|
|
|
if (!candidates[current_class])
|
285
|
157
|
|
|
|
|
|
candidates[current_class] = _new_breakpoint();
|
286
|
295
|
|
|
|
|
|
candidates[current_class]->active = active;
|
287
|
295
|
|
|
|
|
|
candidates[current_class]->demerits = demerits;
|
288
|
295
|
|
|
|
|
|
candidates[current_class]->ratio = ratio;
|
289
|
|
|
|
|
|
|
}
|
290
|
|
|
|
|
|
|
}
|
291
|
|
|
|
|
|
|
active = next;
|
292
|
1364
|
100
|
|
|
|
|
if (!active || active->line >= current_line)
|
|
|
100
|
|
|
|
|
|
293
|
|
|
|
|
|
|
break;
|
294
|
|
|
|
|
|
|
}
|
295
|
|
|
|
|
|
|
debug(warn("Post inner loop\n"));
|
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
|
298
|
687
|
100
|
|
|
|
|
for (t = 0; t <= 3; t++) {
|
299
|
468
|
100
|
|
|
|
|
if (candidates[t]) {
|
300
|
157
|
|
|
|
|
|
Breakpoint* newnode = _new_breakpoint();
|
301
|
157
|
|
|
|
|
|
HV* tmpsum = _compute_sum(self, index, nodes);
|
302
|
157
|
|
|
|
|
|
newnode->position = index;
|
303
|
157
|
|
|
|
|
|
newnode->fitness_class = t;
|
304
|
157
|
|
|
|
|
|
newnode->totals = tmpsum;
|
305
|
|
|
|
|
|
|
debug(warn("Setting previous to %p\n", candidates[t]->active));
|
306
|
157
|
|
|
|
|
|
newnode->previous = candidates[t]->active;
|
307
|
157
|
|
|
|
|
|
newnode->demerits = candidates[t]->demerits;
|
308
|
157
|
|
|
|
|
|
newnode->ratio = candidates[t]->ratio;
|
309
|
157
|
|
|
|
|
|
newnode->line = candidates[t]->line + 1;
|
310
|
157
|
100
|
|
|
|
|
if (active) {
|
311
|
|
|
|
|
|
|
debug(warn("Before\n"));
|
312
|
15
|
|
|
|
|
|
newnode->prev = active->prev;
|
313
|
15
|
|
|
|
|
|
newnode->next = active;
|
314
|
15
|
100
|
|
|
|
|
if (!active->prev) { activelist->head = newnode; }
|
315
|
12
|
|
|
|
|
|
else { active->prev->next = newnode; }
|
316
|
15
|
|
|
|
|
|
active->prev = newnode;
|
317
|
15
|
|
|
|
|
|
activelist->list_size++;
|
318
|
|
|
|
|
|
|
} else {
|
319
|
|
|
|
|
|
|
debug(warn("After\n"));
|
320
|
142
|
100
|
|
|
|
|
if (!activelist->head) {
|
321
|
3
|
|
|
|
|
|
activelist->head = activelist->tail = newnode;
|
322
|
3
|
|
|
|
|
|
newnode->prev = newnode->next = NULL;
|
323
|
|
|
|
|
|
|
} else {
|
324
|
139
|
|
|
|
|
|
newnode->prev = activelist->tail;
|
325
|
139
|
|
|
|
|
|
newnode->next = NULL;
|
326
|
139
|
|
|
|
|
|
activelist->tail->next = newnode;
|
327
|
139
|
|
|
|
|
|
activelist->tail = newnode;
|
328
|
139
|
|
|
|
|
|
activelist->list_size++;
|
329
|
|
|
|
|
|
|
}
|
330
|
|
|
|
|
|
|
}
|
331
|
157
|
|
|
|
|
|
sv_free((SV*)candidates[t]->totals);
|
332
|
157
|
|
|
|
|
|
Safefree(candidates[t]);
|
333
|
|
|
|
|
|
|
}
|
334
|
|
|
|
|
|
|
}
|
335
|
|
|
|
|
|
|
}
|